1. 概要

Gitは、広く使用されている分散バージョン管理システムになっています。 このチュートリアルでは、Gitリポジトリからファイルまたはディレクトリを削除し、そのローカルコピーを保持する方法を見ていきましょう。

2. 問題の紹介

いつものように、例を通して問題を理解しましょう。 GitリポジトリmyRepoで作業しているとしましょう。

$ ls -l
total 12
drwxr-xr-x 2 kent kent 60 May 12 23:00 logs/
-rw-r--r-- 1 kent kent 26 May 11 13:22 README.md
-rw-r--r-- 1 kent kent 21 May 11 13:22 some-file.txt
-rw-r--r-- 1 kent kent 16 May 12 22:40 user-list.txt

リポジトリのクローンをローカルに作成しました。lsの出力が示すように、リポジトリには3つのファイルとlogsディレクトリがあります。

ここで、ファイルuser-list.txtlogsディレクトリをGitリポジトリから削除するとします。 ただし、ローカルの作業コピーからそれらを削除したくありません。

一般的なシナリオは、いくつかのファイルまたはディレクトリをコミットした後、いくつかのファイルを無視する必要があることに気付いた場合です。 したがって、リポジトリから関連ファイルを削除し、ローカルコピーを保持し、対応するパターンを.gitignoreファイルに追加して、Gitがそれらのファイルを追跡しないようにします。

git rmuser-list.txtコマンドがリポジトリからファイルを削除することはわかっています。 ただし、ローカルファイルも削除されます。

もちろん、ファイルとディレクトリを別のディレクトリに移動し、コミットを送信してから、ローカルの作業ディレクトリにコピーして戻すこともできます。 それは問題を解決します。 ただし、このアプローチは、特にファイルまたはディレクトリが大きい場合は非効率的です。

次に、この問題をより効率的に解決する方法を見てみましょう。

3. git rm –cachedコマンドの使用

git rm FILEは、デフォルトでインデックスとローカル作業ツリーからファイルを削除することを説明しました

ただし、 git rm コマンドには、 –cached オプションが用意されており、リポジトリのインデックスからファイルを削除し、ローカルファイルを変更しないでおくことができます。

次に、user-list.txtファイルで試してみましょう。

$ git rm --cached user-list.txt
rm 'user-list.txt'

上記の出力が示すように、user-list.txtファイルは削除されました。 それでは、 gitstatusコマンドを実行して確認してみましょう。

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	deleted:    user-list.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	user-list.txt

ご覧のとおり、user-list.txtは「deleted」です。 さらに、ローカルコピーがまだ存在するため、「追跡されていない」とマークされています。

同様に、logsディレクトリを削除できます。 ただし、これはディレクトリであるため、 -r(再帰的に)オプションを gitrmコマンドに追加で渡す必要があります。

$ git rm --cached -r logs
rm 'logs/server.log'

それでは、変更をコミットしましょう。

$ git commit -m 'remove user-list.txt and logs'
[master ee8cfe8] remove user-list.txt and logs
 2 files changed, 4 deletions(-)
 delete mode 100644 logs/server.log
 delete mode 100644 user-list.txt

次に、 git ls-files コマンドを使用して、現在ステージングされているファイルを確認しましょう。

$ git ls-files -c
.gitignore
README.md
some-file.txt

出力が示すように、ターゲットファイルとディレクトリはもうありません。 また、ローカルコピーが保持されます。 したがって、私たちは問題を解決しました。

必要に応じて、それらを .gitignore ファイルに追加して、Gitがそれらを再度追跡しないようにすることができます。

4. .gitignoreで定義されているすべてのファイルを削除します

場合によっては、Gitのインデックスを確認し、.gitignoreで定義されているすべてのファイルを削除したいことがあります。 .gitignoreの定義が完了したと仮定します。 次に、簡単な方法は3つのステップのプロセスになります。

  • まず、インデックスからすべてのファイルを削除します: git rm -r –cached
  • 次に、すべてのファイルを再度ステージングします。 .gitignore で定義されたファイルは自動的に無視されます: git add
  • 変更をコミットします: gitcommit-m「適切なコミットメッセージ」

または、現在追跡されているが、無視する必要があるファイルのみを検索して削除することもできます git ls-files コマンドは、ファイルを見つけるのに役立ちます。

以前のコミットを元に戻し、user-list.txtファイルとlogsディレクトリを再度削除しましょう。 今回は、まずそれらを.gitignoreファイルに追加しましょう。

$ cat .gitignore
user-list.txt
logs/

次に、Gitインデックスから削除したいファイルを見つけましょう。

$ git ls-files -i -c -X .gitignore
logs/server.log
user-list.txt

ご覧のとおり、上記のコマンドには、削除するステージングされたファイルがリストされています。

それでは、 git rm –cachedコマンドとgit ls-filesコマンドを組み合わせて、それらを1回で削除しましょう

$ git rm --cached $(git ls-files -i -c -X .gitignore)
rm 'logs/server.log'
rm 'user-list.txt'

このコマンドはlogsディレクトリの下にあるすべてのファイルを削除するため、最後に、インデックスから空のログディレクトリを削除することに注意してください。 したがって、この例では、logsディレクトリの下にファイルが1つだけあります。

ここで、ステージングされたファイルを確認すると、削除されたファイルはなくなります。

$ git ls-files -c
.gitignore
README.md
some-file.txt

そしてもちろん、user-list.txtlogs/はまだローカルの作業ツリーにあります。

$ ls -l
total 12
drwxr-xr-x 2 kent kent 60 May 13 00:45 logs/
-rw-r--r-- 1 kent kent 26 May 11 13:22 README.md
-rw-r--r-- 1 kent kent 21 May 11 13:22 some-file.txt
-rw-r--r-- 1 kent kent 16 May 13 00:45 user-list.txt

5. 削除されたファイルはまだGit履歴にあります

git rm –cachedコマンドを使用して問題を解決しました。 ただし、Gitのトラッキングインデックスからファイルを削除しただけであることに注意してください。 Gitのコミット履歴でファイルとそのコンテンツを引き続き確認できます。 たとえば、以前のコミットを確認することで、user-list.txtのコンテンツを引き続き確認できます。

$ git show 668fa2f user-list.txt
commit 668fa2f...
Author: ...
Date:   ...

    add user-list.txt and some-file.txt

diff --git a/user-list.txt b/user-list.txt
new file mode 100644
index 0000000..3da7fab
--- /dev/null
+++ b/user-list.txt
@@ -0,0 +1,3 @@
+kent
+eric
+kevin

クレデンシャルなどの機密ファイルを.gitingoreファイルに追加するのを忘れることがあるため、これを知ることは重要です。 しかし、私たちはそれらをコミットし、変更をリモートリポジトリにプッシュしました。 気付いたら、Gitの履歴から機密ファイルを完全に消去したい場合があります。

この場合、Gitのコミット履歴からファイルを削除する必要があります。

6. 結論

この記事では、Gitリポジトリからファイルまたはディレクトリを削除する方法を示しましたが、例を通してそのローカルコピーを保持します。

また、.gitignoreファイルで定義されているすべてのファイルをすばやく削除する方法についても説明しました。 最後に、 git rm –cached によって削除されたファイルは、Gitのコミット履歴に残っていることを覚えておく必要があります。