git でファイルを過去の履歴から除外する
git を使っていて,後からファイルをリポジトリから削除したいという場合があります.
git rm
を用いるとファイルをリポジトリから削除することが可能ですが,今回は過去の履歴からもファイルを除外したい場合の操作について紹介します.
ファイルをリポジトリから削除するgit rm
ファイルを git 管理から除外する方法としてgit rm
を用いる方法があります.
$ git rm trash.txt # trash.txt を git 管理から除外 + trash.txt 自体も削除 $ git rm --cached trash.txt # trash.txt を git 管理から除外
git rm
を実行後,commit することでファイルを除外したことが記録されます.
ファイルを過去の履歴からも除外する
git rm
では,ファイルを除外したことを記録することになりますが,既にリポジトリに記録されているファイルを,過去の履歴からも除外したい場合もあると思います.
そこで,以下のような履歴のリポジトリを例に,trash.txt を過去の履歴から除外する場合について解説していきます.
$ git log --graph --pretty="%h %s" --stat * 322d421 Update files | | sample.txt | 1 + | trash.txt | 1 + | 2 files changed, 2 insertions(+) * 1aa7e6b Add files | | sample.txt | 1 + | trash.txt | 1 + | 2 files changed, 2 insertions(+) * 8f832af Initial commit
1. rebase を行う
まず,trash.txt が追加された commit の1つ前のコミットハッシュ値を指定し rebase を行います.
$ git rebase -i 8f832af
エディタが起動し,以下の内容が表示されます.
pick 1aa7e6b Add files pick 322d421 Update files # Rebase 8f832af..322d421 onto 8f832af (2 command(s)) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
1行目の pick を edit へ変更し,保存・終了します.
edit 1aa7e6b Add files pick 322d421 Update files # Rebase 8f832af..322d421 onto 8f832af (2 command(s)) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
以下のように,edit を指定した commit で停止します.
Stopped at 1aa7e6b... Add files You can amend the commit now, with git commit --amend Once you are satisfied with your changes, run git rebase --continue
2. ファイルを削除
現在1aa7e6b
の commit で停止しているので,git rm
を用いて trash.txt を除外した後,git commit --amend
で commit を修正します.
$ git rm --cached trash.txt $ git commit --amend
以下のように,元のコミットメッセージが入った状態でエディタが起動するので,メッセージに変更が無い場合はそのまま保存・終了します.
Add files # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Mon Aug 15 22:35:48 2016 +0900 # # interactive rebase in progress; onto 8f832af # Last command done (1 command done): # edit 1aa7e6b Add files # Next command to do (1 remaining command): # pick 322d421 Update files # You are currently editing a commit while rebasing branch 'master' on '8f832af'. # # Changes to be committed: # new file: sample.txt # # Untracked files: # trash.txt #
3. rebase を継続する
trash.txt を追加していた commit の修正が終わったので,git rebase --continue
で次の commit へ処理を移行します.
次の commit は322d421
ですが,先ほどgit rebase -i
で開いたエディタで,pick を指定してあるため,何もせず元の commit を利用するはずです.
しかし,2. で直前の commit を trash.txt を無かったことにする修正を加えたため,以下のようにエラーが出ます.
$ git rebase --continue error: refusing to lose untracked file at 'trash.txt' error: could not apply 322d421... Update files When you have resolved this problem, run "git rebase --continue". If you prefer to skip this patch, run "git rebase --skip" instead. To check out the original branch and stop rebasing, run "git rebase --abort". Could not apply 322d421dd371d4483a53050e19ddb43e61b69fe5... Update files
git status
で状況を確認すると,以下のように trash.txt が削除されているためコンフリクトが発生していることが分かります.
$ git status interactive rebase in progress; onto 8f832af Last commands done (2 commands done): edit 1aa7e6b Add files pick 322d421 Update files No commands remaining. You are currently rebasing branch 'master' on '8f832af'. (fix conflicts and then run "git rebase --continue") (use "git rebase --skip" to skip this patch) (use "git rebase --abort" to check out the original branch) Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: sample.txt Unmerged paths: (use "git reset HEAD <file>..." to unstage) (use "git add/rm <file>..." as appropriate to mark resolution) deleted by us: trash.txt
git rm
で trash.txt を除外してあげます.
$ git rm --cached trash.txt trash.txt: needs merge rm 'trash.txt'
git status
で状況を確認すると,以下のように先ほどと異なる結果となっています.
ここでgit commit --amend
を行ってはいけません
8行目に (all conflicts fixed: run "git rebase --continue")
とあるので,git rebase --continue
を実行します.
$ git status interactive rebase in progress; onto 8f832af Last commands done (2 commands done): edit 1aa7e6b Add files pick 322d421 Update files No commands remaining. You are currently rebasing branch 'master' on '8f832af'. (all conflicts fixed: run "git rebase --continue") Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: sample.txt Untracked files: (use "git add <file>..." to include in what will be committed) trash.txt $ git rebase --continue
エディタが起動し,元 (322d421
の commit) のコミットメッセージが入力されています.
変更が無い場合,そのまま保存・終了します.
Update files # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # interactive rebase in progress; onto 8f832af # Last commands done (2 commands done): # edit 1aa7e6b Add files # pick 322d421 Update files # No commands remaining. # You are currently rebasing branch 'master' on '8f832af'. # # Changes to be committed: # modified: sample.txt # # Untracked files: # trash.txt #
エディタを閉じると,以下のように rebase が完了します.
[detached HEAD d783042] Update files 1 file changed, 1 insertion(+) Successfully rebased and updated refs/heads/master.
git log
を実行すると,trash.txt が除外されていることが確認できます.
$ git log --graph --pretty="%h %s" --stat * d783042 Update files | | sample.txt | 1 + | 1 file changed, 1 insertion(+) * 7af8d82 Add files | | sample.txt | 1 + | 1 file changed, 1 insertion(+) * 8f832af Initial commit
まとめ
git でファイルを過去の履歴からも除外する方法を紹介しました.
ポイントは,edit に変更した commit 以外(すなわち pick の commit)では,git commit --amend
ではなく,git rebase --continue
を実行することです.
コンフリクト時にgit commit --amend
を実行してしまうと,以下のように,元の commit (Update files
) ではなく,直前の edit で trash.txt を除外する修正を行った commit (Add files
) と1つになってしまうため,注意が必要です.
$ git log --graph --pretty="%h %s" --stat * 97c757b Add files | | sample.txt | 2 ++ | 1 file changed, 2 insertions(+) * 8f832af Initial commit