Gitでファイルのリネームと削除を行う話

そういえば、リネームや削除には触れてなかったので、
それについても書こうと思います。

削除したら、”削除した”という情報をコミットします。
リネームも、”リネームした”という情報をコミットします。
これらは、ファイルの追加や編集と同じですね。

“ファイルの追加”、もしくは”編集した”という情報は、
git addを実行することでコミットの対象になります。
このコミット対象になっていることを入門Git(Amazon)では、
インデックスに記録された状態」と表現しています。

つまり、リネームや削除もインデックスに記録して、
それからコミットする必要があります。

ちなみに、git statusを実行すると、
インデックスの状態を確認することができます。

では、さっそく確認してみましょう。

まずは、ローカルリポジトリを作ります。
$ git init
$ git status
# On branch master
#
# Initial commit
#
nothing to commit (create/copy files and use "git add" to track)

適当にファイルを作成してみます。
$ echo foo >> readme.txt
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add ..." to include in what will be committed)
#
# readme.txt

次に、”ファイルの追加”をインデックスに記録します。
$ git add readme.txt
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached ..." to unstage)
#
# new file: readme.txt
#

そして、コミットします。
$ git commit -m "初回コミット"
[master (root-commit) 6b089d7] 初回コミット
1 file changed, 1 insertion(+)
create mode 100644 readme.txt
nekoair:Work nekoair$ git status
# On branch master
nothing to commit, working directory clean

ここでのポイントは、git statusの結果が毎回異なる点です。
例えば、ファイルを作成したときは”ファイルの追加”をインデックスに記録する方法が、
インデックスに記録したときはインデックスから削除する方法が表示されています。

ちなみに、
$ git rm --cached <file>
--cachedは、ファイル自体は削除しないことを意味しています。

次に、もう一つファイルを追加してみます。
$ echo aaa >> tmp.txt
$ git add tmp.txt
$ git commit -m "一時ファイルを追加"
[master 54bb151] 一時ファイルを追加
1 file changed, 1 insertion(+)
create mode 100644 tmp.txt

そして、”リネームした”ことをインデックスに記録してみます。
$ ls
readme.txt tmp.txt
$ git mv tmp.txt data.txt
$ ls
data.txt readme.txt
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# renamed: tmp.txt -> data.txt
#

リネームは、基本的にgit mvで行います。
ここでのポイントは、git mvでリネームすると、
この時点ですでに、”リネームした”ことがインデックスに記録されている点です。

では、一旦、コミットしてみましょう。
$ git commit -m "適切なファイル名へ変更"
[master ce7a7e5] 適切なファイル名へ変更
1 file changed, 0 insertions(+), 0 deletions(-)
rename tmp.txt => data.txt (100%)

“tmp.txt”には、何かしらのデータが記録されていたという設定です。
では、これをリネーム前に戻すにはどうしたら良いでしょう?

試しに、以下のコマンドを実行してみます。
$ git reset --soft HEAD^
$ ls
data.txt readme.txt
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# renamed: tmp.txt -> data.txt
#

どうやら、”リネームした”ことをインデックスに記録した状態に戻ったようです。
では、もう一度コミットして、違うコマンドを試してみましょう。
$ git commit -m "適切なファイル名へ変更"
[master c56aa55] 適切なファイル名へ変更
1 file changed, 0 insertions(+), 0 deletions(-)
rename tmp.txt => data.txt (100%)

次は、どうなるでしょう?
$ git reset --hard HEAD^
HEAD is now at e0139c7 一時ファイルを追加
$ ls
readme.txt tmp.txt
$ git status
# On branch master
nothing to commit, working directory clean

これが正解のようです。
ファイル名を変更する必要があったため、
--softではなく、--hardを使わなければならなかったようです。

これで、リネームの方法が分かりました。
ところで、git mvを使わずにリネームしてしまった場合はどうなるでしょう?
GUIでリネームした場合や、mvコマンドでリネームした場合のことです。

では、mvコマンドでリネームして確認してみましょう。
$ mv tmp.txt data.txt
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# deleted: tmp.txt
#
# Untracked files:
# (use "git add ..." to include in what will be committed)
#
# data.txt
no changes added to commit (use "git add" and/or "git commit -a")

さて、メッセージを読んでみましょう。
まず、消しちゃったファイルに関しては、
git addないし、git rmでインデックスに記録する方法が表示されています。
次に、管理されていないファイルがあるので、
“ファイルの追加”をインデックスに記録する手順が表示されています。

では、表示された通りにやってみます。
$ git rm tmp.txt
$ git add data.txt
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# renamed: tmp.txt -> data.txt
#

驚きましたか?ファイルの内容を見て、”リネームした”と判断されたのです。
ですが、もう一つ方法があります。

一旦、mvコマンドを使った直後に戻します。
$ git reset HEAD

そして、Git Guiを起動してみます。
$ git gui

すると、削除されたはずの”tmp.txt”があるので、それをインデックスに記録します。
Git Guiでは、”tmp.txt”を選択し、[コミット]-[コミット予定する]をクリックします。
これで、”削除した”ことがインデックスに記録されました。
次に、”data.txt”も同様の方法で、インデックスに記録します。
これで、インデックスへの記録が完了しました。

では、一旦、Git Guiを閉じて確認してみましょう。
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# renamed: tmp.txt -> data.txt
#

さっきと同じですね。
では、コミットを済ませて、次に進みましょう。
$ git commit -m "適切なファイル名へ変更"

次は、”data.txt”を削除します。
やり方は想像つきますね?
$ git rm data.txt
rm 'data.txt'
$ ls
readme.txt

今回は、--cachedを付けてないので消えてしまいました。
そして、もちろんこの時点でインデックスにも記録されています。
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# deleted: data.txt
#

今回も、元に戻す場合はファイルを復元する必要があるので、
--hardを付けてgit resetを実行します。
$ git reset --hard HEAD

そして、もしGUIやrmコマンドで削除してしまった場合は・・・、
これは宿題ということで良いですね。
ヒントは、リネームでやったことを思い出してください。

では、最後に”data.txt”を削除して、今回は終わりにしたいと思います。
$ git rm data.txt
$ git commit -m "使わないので削除"

これで、リネームと削除は終わりです。
お疲れさまでした。

おしまい。

Leave a Comment