git addの取り消しと、コミット済みのファイルを除外する方法

git addを取り消す

$ git reset HEAD foo.txt

git add で編集内容が index に追加*1されます。
間違えて index に追加した場合に、このコマンドで取り消しができます。

$ git add foo.txt 
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   foo.txt
#
$ git reset HEAD foo.txt 
Unstaged changes after reset:
M	foo.txt
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   foo.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

間違えて foo.txt を index に追加し、取り消しました。

$ mkdir test
$ cd test/
$ git init
Initialized empty Git repository in /Users/myuser/Dev/test/.git/
$ touch foo.txt
$ git add foo.txt 
$ git reset HEAD foo.txt
fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

ただ、まっさらのリポジトリに初めてコミットする際、コミットするファイルを index に追加しますが、それは取り消しが出来ませんでした。

コミット済みのファイルを、リポジトリから消して.gitignoreで除外する

$ git rm --cached foo.txt
$ echo 'foo.txt' > .gitignore
$ git add .gitignore
$ git commit -m 'delete and add .gitignore'

既にコミットされてるファイルを、後から .gitignore で除外したくなった際、まずはリポジトリから削除しないと除外できません。
リポジトリからは消したいけど、ワーキングツリーにあるファイルは現状のまま残しておきたい場合に、この操作で除外できます。

$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   foo.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git rm --cached foo.txt
rm 'foo.txt'
$ echo 'foo.txt' > .gitignore
$ git add .gitignore
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	new file:   .gitignore
#	deleted:    foo.txt
#
$ git commit -m 'delete and add .gitignore'
[master 6bd9dbd] delete and add .gitignore
 2 files changed, 1 insertions(+), 1 deletions(-)
 create mode 100644 .gitignore
 delete mode 100644 foo.txt
$ cat foo.txt 
foo
$ echo 'bar' > foo.txt 
$ git status
# On branch master
nothing to commit (working directory clean)
$ cat foo.txt
bar

foo.txt をリポジトリから消しつつ .gitignore で foo.txt を除外しました。

*1:indexはstageとも呼ばれるぽい。git status で表示される説明では git addを取り消す事に unstage という動詞を使ってます。