CH 13 / 75第2部 Gitの基礎 ── 手元で完結する操作

ファイルの移動・削除・追跡の解除

このページで分かること

  • 記録済みのファイルの名前を git mv で変えられる
  • 記録済みのファイルを git rm で消せる
  • 手元に残したまま追跡だけをやめる git rm --cached を使える
  • 誤って消したファイルを最後の記録から戻せる
このページの目次10 items

第2部の12で、.gitignore は一度記録したファイルには効かないことを見ました。このページでは、記録済みのファイルを動かす・消す・追跡から外すときの正しい手順を扱います。どれも、ファイルの操作と Git への報告を1回で済ませるコマンドです。

追跡の状態と、それを変えるコマンド#

Git から見ると、フォルダの中のファイルは「追跡中」(一度でもコミットしたもの)か「未追跡」かのどちらかです。第2部の12の .gitignore は、未追跡のファイルをさらに「無視」に振り分けるものでした。

やりたいこと コマンド ファイル 追跡
記録の対象にする git add そのまま 未追跡 → 追跡中
名前を変える・移動する git mv 旧 新 名前が変わる 追跡中のまま
消す git rm 消える 追跡をやめる
手元に残して追跡だけやめる git rm --cached そのまま 追跡中 → 未追跡

どのコマンドも、実行した時点ではステージに載るだけです。記録にするには、いつもどおり git commit が必要です。

名前を変える:git mv#

memo.txt を、中身に合った名前の shopping.txt に変えます。

text9 lines
cd ~/git-practice
git mv memo.txt shopping.txt
git status

# 出力:
# On branch main
# Changes to be committed:
#   (use "git restore --staged <file>..." to unstage)
#   renamed:    memo.txt -> shopping.txt
text1 lines
git commit -m "memo.txt を shopping.txt に名前変更"

以降のページでは、買い物のメモは shopping.txt として扱います。

git mv を使わずに名前を変えた場合#

Finder やエクスプローラー、または mv コマンドで名前を変えても問題はありません。ただし、Git からは次のように見えます。

text6 lines
mv todo.txt todo-list.txt
git status -s

# 出力:
#  D todo.txt
# ?? todo-list.txt

「todo.txt が消えて、todo-list.txt という知らないファイルが現れた」という見え方です。両方を git add すると、Git は中身がほぼ同じであることに気づき、名前の変更としてまとめ直します。

text5 lines
git add todo.txt todo-list.txt
git status -s

# 出力:
# R  todo.txt -> todo-list.txt

git mv は、この「名前を変えて、両方を git add する」を1回で行うコマンドです。結果は同じなので、どちらを使っても構いません。

この練習で名前を変えた todo-list.txt は、元の名前に戻しておきます。

text2 lines
git restore --staged todo.txt todo-list.txt
mv todo-list.txt todo.txt

消す:git rm#

text4 lines
git rm todo.txt

# 出力:
# rm 'todo.txt'

ファイルがワークツリーから消え、「削除した」という変更がステージに載ります。ここで git commit すれば、以降のコミットには todo.txt が含まれなくなります。ただし、過去のコミットの中には残っています。消したファイルが必要になっても、履歴から取り出せます。

今回は消さずに残すので、元に戻します。

text2 lines
git restore --staged todo.txt
git restore todo.txt

1行目で削除をステージから降ろし、2行目で最後の記録からファイルを書き戻しています。

誤って消したとき#

git rm を使わずに、ふつうに削除した場合も同じです。

text7 lines
rm todo.txt
git status -s

# 出力:
#  D todo.txt

git restore todo.txt

コミットしていない段階なら、git restore ファイル名 で最後に記録した内容に戻せます。戻るのは最後に記録した時点の内容なので、記録していなかった編集は戻りません。

編集中のファイルは消せない#

text7 lines
echo "郵便局に行く" >> todo.txt
git rm todo.txt

# 出力:
# error: the following file has local modifications:
#     todo.txt
# (use --cached to keep the file, or -f to force removal)

記録していない変更があるファイルを git rm すると、Git は止めます。その変更は記録のどこにも残っていないので、消すと二度と戻らないためです。確かめたら、追記した行は捨てておきます(git restore todo.txt)。

追跡だけやめる:git rm –cached#

パスワードを書いた設定ファイルを、うっかりコミットしてしまった場面を再現します。

text3 lines
echo "API_KEY=abc" > config.txt
git add config.txt
git commit -m "設定を追加"

このファイルは手元では必要ですが、記録には入れたくありません。--cached を付けると、ファイルは手元に残したまま、Git の追跡だけをやめます。

text16 lines
git rm --cached config.txt

# 出力:
# rm 'config.txt'

git status

# 出力:
# On branch main
# Changes to be committed:
#   (use "git restore --staged <file>..." to unstage)
#   deleted:    config.txt
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#   config.txt

Git からは「記録からは削除」「手元には未追跡のファイルとして存在」と見えています。このままでは次の git add . で戻ってしまうので、同時に .gitignore にも書き、まとめてコミットします。

text3 lines
echo "config.txt" >> .gitignore
git add .gitignore
git commit -m "config.txt を追跡から外す"

これで config.txt は、手元には残り、以降のコミットには入らず、git status にも表示されなくなります。

よくある疑問#

Q. フォルダごと消したり移動したりできますか?
A. できます。git mv 旧フォルダ 新フォルダ、フォルダを消すときは git rm -r フォルダ です。-r は「中身ごと」の指定です。

Q. 第2部の08で出てきた git rm --cached と同じものですか?
A. 同じです。最初のコミットの前にステージから降ろすとき、Git がヒントとして出していたのはこのコマンドでした。まだ記録が1つもないので、「降ろす」と「追跡をやめる」が同じ意味になります。

まとめ#

  • git mv は名前の変更を、git rm は削除を、ファイルの操作と同時にステージに載せる
  • Git は名前の変更を、前後の中身を比べて判定している
  • 消したファイルも、コミット前なら git restore で最後の記録の内容に戻せる
  • git rm --cached は、ファイルを手元に残したまま追跡だけをやめる。.gitignore と組み合わせて使う
  • 追跡から外しても、過去のコミットの中身は消えない

次のページ#

14. やり直す①(restore・reset・amend) ── 編集・ステージ・直前のコミットと、段階ごとの「なかったことにする」方法を使い分けます。