シーン別 Git チートシート
目次
チートシート
初期化と複製
現在のディレクトリで Git を利用開始する
git init
既存のレポジトリを手元に複製して利用する
git clone <repository>
ファイル操作
現在のワーキングツリーとインデックスの状態の確認
git status
ファイルの最新の状態をインデックスに追加(ステージング)する。<path>
がディレクトリの場合はディレクトリ内のすべてのファイルが対象となる。
git add <path>
ディレクトリの中のすべてのファイルをインデックスに追加する
git add <dir>
ステージングをキャンセルする
git reset <path>
ファイルを編集前の状態(HEAD
)に復元する
git checkout HEAD <path>
ファイルをインデックスの状態に復元する
git checkout <path>
ファイルを削除する
git rm <path>
ファイルを移動する
git mv <src> <dst>
トラックされていないファイルを消す
git clean -f
レポジトリを作業前の状態に戻す
git checkout HEAD . && git clean -f
コミット
ステージングされたファイルをコミットとして記録する。-m <message>
でコミットメッセージを指定。
git commit [-m <message>]
直前のコミットを修正する
git commit --amend
履歴の表示
git log
詳細解説
Git - Bookは非常に丁寧にわかりやすく書かれており、トピックも十分に広く・深くカバーされています。Git - Bookは日本語版もあります。読んだことがなくgitを何となく使用している人は一度目を通すべきでしょう。
git-scm.com
のページは検索ではあまり上位には出てきませんが、ちまたのgit入門サイトを読むより公式の正しいドキュメントを目を通すほうが遥かにためになると思います。このドキュメントの目的もあくまで備忘録用によく使うコマンドを逆引きで一覧にすることです。詳細な情報やチュートリアルは公式の情報を参照してください。
Git レポジトリの作成と複製
現在のレポジトリで Git の利用を開始するにはgit init
を実行します
$ git init
Initialized empty Git repository in /home/yunabe/src/myrepository/.git/
既存のレポジトリを手元に複製(クローン)するにはgit clone
を実行します。
git clone <repository> [<directory>]
<repository>
は多くの場合 GitHub などのリモートサーバー上のレポジトリを指しますが、ローカルディスク上のレポジトリを指定することも可能です。複製先のディレクトリ名<direcotyr>
は省略可能です。
$ git clone https://github.com/yunabe/codelab mylab
Cloning into 'mylab'...
remote: Enumerating objects: 34, done.
remote: Counting objects: 100% (34/34), done.
remote: Compressing objects: 100% (25/25), done.
remote: Total 2624 (delta 6), reused 32 (delta 5), pack-reused 2590
Receiving objects: 100% (2624/2624), 1.71 MiB | 1.39 MiB/s, done.
Resolving deltas: 100% (1069/1069), done.
init
, clone
ともに --bare
というオプションを持っており、--bare
を指定した場合にはgit push
が行える裸のレポジトリ(bare repository)が作成されます。
ワーキングツリーとインデックスの操作
Git ではファイルは、ローカルで編集済み → ステージ済み → コミット済みという手順を経てレポジトリに記録されます。まずはじめにコミットするまえにローカルでファイルを編集したり、それをインデックスにステージするためのコマンド類をまとめます。
git status
: ワーキングツリーとインデックスの状態を表示
どのファイルがワーキングツリー上で編集されているか、どのファイルがインデックスにステージングされているかなどはgit status
で表示します。
git status
git add
: ワーキングツリーのファイルをインデックスに反映する(ステージング)
Git ではコミットする前に、変更を「インデックス」に対してアップロードする必要があります。ワーキングツリー(作業ツリー)上の現在のファイルの状態をインデックスに反映する(ステージする)にはgit add
を使います。
git add <path>
add
という名前のコマンドですが、ワーキングツリー上のファイルの状態をインデックスに反映するコマンドなので、削除されたファイルをgit add
するとインデックスからもファイルが削除されます。「ファイルが削除された状態」をインデックスにadd
するのです。
$ rm hello.txt && git status
On branch master
Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: hello.txt
$ git add hello.txt && git status
On branch master
Changes to be committed: (use "git reset HEAD <file>..." to unstage)
deleted: hello.txt
<path>
にディレクトリを指定するとディレクトリ内のすべてのファイルがgit add
されます。git add
以外のコマンドもディレクトリを指定するとそのディレクトリ内のすべてのファイルを指定したことになることが多いです。現在のディレクトリ内のすべてのファイルの追加、削除、変更操をgit add
するにはgit add .
を実行します。
.
の代わりに--all
あるいは-A
を渡すとレポジトリ内のすべてのファイルがgit add
されます (レポジトリのルートでgit add .
したのと同等の結果)。Git1.x の名残でgit add --all
をみかけることのほうが多いかもしれませんが、Git2.x 系列においてわざわざ--all
を覚えておく必要はあまりないように思います。
git reset
: ステージングをキャンセルする
git add
で行ったインデックスへのステージングを取り消すにはgit reset
を使います。--
は<path>
がワーキングツリーに存在する場合は省略可能です。
git reset [--] <path>
先程、git add
でインデックスから削除した hello.txt を復元してみましょう。このケースではhello.txt
がローカルに存在しないので--
は省略できません。
$ git reset -- hello.txt
Unstaged changes after reset:
D hello.txt
$ git status
On branch master
Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: hello.txt
no changes added to commit (use "git add" and/or "git commit -a")
インデックスに登録されていたhello.txt
の削除がキャンセルされているのがgit status
で確認できます。
git rese
も<path>
にディレクトリを指定した場合にはディレクトリ内のすべてのファイルがgit reset
されます。それと、後述するようにgit reset
にはHEAD
を移動するという全く別の機能も割り当てられているので、やはり混乱しないように違いに気をつけてください。
git checkout
: ファイルを復元する
ファイルを編集前の状態に戻すにはgit checkout
を使用します。まずインデックス上のファイルの状態を復元するには
git checkout [--] <path>
を実行します。対象のファイルが特にインデックス上で編集されていなければ、そのファイルのインデックス上の状態はHEAD
と同じなので直前のコミットからファイルが復元されます。
コミットされたファイルの状態を復元するときには、git checkout
をコミットとともに実行します。
git checkout <commit> [--] <path>
一番良く使うのは git checkout HEAD <path>
でしょう。このコマンドコミットを実行するとファイルの状態がワーキングツリーに復元されるだけでなく、インデックスにも復元されます。つまり、インデックスされている変更も元に戻されてしますので注意してください。インデックスは変更せずにローカルにだけファイルを復元する方法はなぜか用意されていません。ちなみにインデックスにだけファイルを復元したい場合、言い換えればステージングをなかったことにしたい場合には前述したようにgit reset
を使用してください。
またgit checkout
コマンドはファイル名を省略することで、全く異なる処理(git checkout master
など)に利用されるので混乱しないよう違いをしっかりと覚えてください。
git rm
: ファイルを削除する
Git にはファイルをワーキングツリーから削除し、それをインデックスに反映するgit rm
コマンドが用意されています。
git rm <path>
これはrm <path>
でワーキングツリーからファイルを削除してそれをgit add <path>
でインデックスに反映した場合と同じ結果が得られます(git rm
は対象のファイルが編集されていない場合にしか利用できないなど細かい点は少し異なる)。
ワーキングツリーからはファイルを削除せずに、インデックスからのみ削除したい場合には--cached
フラグを渡します。
git rm --cached <path>
git mv
: ファイルを移動する
Git にはファイルを移動し、その移動をインデックスに反映するgit mv
コマンドが用意されています。
git mv <src> <dst>
他のバージョン管理システムのユーザーには信じられないと思いますが、Git はファイルの移動履歴をトラッキングしません(If you rename a file in Git, no metadata is stored in Git that tells it you renamed the file.)。そのため、mv <src> <dst>
でワーキングツリー上のファイルを移動してから、git add <src> <dst>
で移動元、移動先のファイルの状態をインデックスに反映してもgit mv
したのと場合と全く同じ結果が得られます。
ちなみにファイルのコピーを行うgit cp
というコマンドは存在しません。なんででしょうね。
レポジトリ全体を元の状態に戻す
レポジトリ全体を編集前の元の状態(HEAD
)に戻すにはレポジトリのルートディレクトリで以下のコマンドを実行します:
git checkout HEAD .
git clean -f
前述したようにまずgit checkout HEAD .
でワーキングツリーとインデックスをHEAD
の状態に戻します。.
を指定することでディレクトリ内のすべてのファイルがもとに戻されます。
git checkout
はトラックされていないファイルに関しては何もしないので、必要であればgit clean
で不要なファイルも削除します。ちなみに最初のgit checkout
はgit reset --hard HEAD
でも代用できます。
git clean
: トラックされていないファイルの削除
手元でいろいろな作業を繰り返してできてしまったワーキングツリー上の一時的なファイルはgit clean
で一括削除できます。もちろん.gitignore
で指定されているファイルは削除されません。
git clean -f
-
-f
git clean
で削除したファイルは復元できないからなのか、git clean
は-f
で削除を強制するか-i
でインタラクティブモードで動かさないと機能しません。でもgit checkout .
などの他の不可逆的なコマンドは-f
なしで動くのですが。
-
-i
- インタラクティブに削除するファイルを選択します。
-
-x
.gitignore
に指定されているファイルも削除します。
git stash
: コミットしていない変更を一時避難する
Gitの様々なコマンドはローカルの変更を間違って破壊しないように、コミットされていない変更がローカルあると失敗します。そのような場合に、ローカルの変更を一時的に別の場所に避難しておき、他の作業が終わってから復元できると便利です。Gitにはgit stash
という便利なコマンドが用意されています。stashは「隠す」という意味です。
git stash push
で現在のローカルにある変更を一時避難します。push
は省略可能です。-m
で通常のコミットのようにコミットメッセージを追加することも可能です。
git stash [push]
git stash list
でstashされた変更をリスト表示します
$ git stash list
stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation
stash@{1}: On master: 9cc0589... Add git-stash
git stash show -p [<stash>]
でstashの中身を表示します。<stash>
が省略された場合は最新のもの(stash@{0}
)が表示されます。
git stash show -p stash@{1}
stashした変更の復元はgit stash pop [stash]
で行います。
git stash pop
不要なstashはgit stash drop [stash]
で削除できます。
git commit
: 変更をコミットとして記録する
上記のコマンドでインデックスが、コミットとして記録したい状態になったらgit commit
で変更をコミットとして記録します。
git commit
エディターが起動しするのでコミットメッセージを書いてエディタを閉じるとコミットが作成されます。-m <message>
を渡すとコミットメッセージをコマンドラインから指定することも可能です。
git commit --amend
: 直前のコミットを修正する
git commit
した直後に、間違いがあることに気がついてgit commit
をやり直したいことがよくあります。そんなときにはgit commit --amend
を使います。
git commit --amend
間違えのあったファイルを修正し、git add
で修正をステージングし、git commit --amend
を実行することで直前のコミットが破棄され、新しい修正済みのコミットが作成されます。
git log
: 履歴の表示
Git でコミットの履歴を表示するにはgit log
を使用します。
$ git log
commit 8dca754b1e874719a732bc9ab7b0e14b21b1bc10 (HEAD -> master, origin/master, origin/HEAD)
Author: Junio C Hamano <gitster@pobox.com>
Date: Fri Jun 21 11:26:11 2019 -0700
The third batch
Signed-off-by: Junio C Hamano <gitster@pobox.com>
commit 90d79d71910415387590a733808140e770382b2f
Merge: f9089e8491 fc7e03aace
Author: Junio C Hamano <gitster@pobox.com>
…
グラフを構造を表示
git log --graph
でコミットのグラフ構造がアスキーアートで表示されます。ログを簡易表示する--oneline
と組み合わせて表示するとコミットグラフの様子が把握しやすいでしょう。
$ git log --graph --oneline
* 8dca754b1e (HEAD -> master, origin/master, origin/HEAD) The third batch
* 90d79d7191 Merge branch 'mo/clang-format-for-each-update'
|\
| * fc7e03aace clang-format: use git grep to generate the ForEachMacros list
* | f9089e8491 Merge branch 'md/url-parse-harden'
|\ \
| * | d37dc239a4 url: do not allow %00 to represent NUL in URLs
| * | 3f6b8a6177 url: do not read past end of buffer
* | | e694ea5e04 Merge branch 'an/ignore-doc-update'
|\ \ \
| * | | 1a58bad014 gitignore.txt: make slash-rules more readable
| |/ /
* | | 755793bf57 Merge branch 'ab/hash-object-doc'
|\ \ \
コミットの内容の表示
git log
はデフォルトで変更のメタ情報のみを表示します。実際の変更に関する情報を表示するにはここに書かれているオプションを使用します。。
-
ファイルの編集内容(patch)を表示する
-p
(あるいは-u
,--patch
)
-
ファイル編集の統計情報(stat)を表示。
--stat
コミットのフィルタリング
git log
は特定の条件にマッチするコミットをフィルタして表示することができます。
-
作成者(Author)でフィルタ
git log --author=<pattern>
(あるいは--committer=<pattern>
)
-
表示件数を制限
git log -n <number>
(あるいは--max-count=<number>
)
-
先頭をスキップ
git log --skip=<number>
-
編集されたファイル/ディレクトリ
git log -- <path>
(--
は省略可)
-
日付でフィルタリング
--begin=<date>
,--since=<date>
,--end=<date>
,--until=<date>
git diff
: 差分の表示
git で差分を表示するにはgit diff
を使います。ワーキングツリー(作業ツリー), インデックス, コミットなど差分を表示したい対象によってオプションを使い分けます。
ワーキングツリーの diff
git diff [<commit>]
ワーキングツリーをインデックスや他のコミットと比較するときには上記のフォーマットを使います。<commit>
が省略されるとワーキングツリーとインデックスの比較になり、<commit>
が指定されているとワーキングツリーと指定したコミットとの差分が表示されます。
ワーキングツリーをインデックスと比較する
現在のディレクトリの状態をインデックスと比較するには単にgit diff
を実行します。
git diff
ワーキングツリーを HEAD(先頭のコミット)と比較する
現在のディレクトリの状態を先頭のコミットと比較するにはgit diff HEAD
を実行します。
git diff HEAD
インデックスの diff
git diff --cached [<commit>]
インデックス(ステージされた変更)を他のコミットと比較するときには上記のフォーマットを使います。<commit>
が省略されるとインデックスとHEAD
の比較となります。--cached
は--staged
でも代用できます。
2つのコミットを比較する
git diff <commit> <commit>
git
で2つのコミットの差分を表示するにはgit diff <commit> <commit>
のフォーマットを使います。1つ目のコミットが差分のベースとなります。また<commit> <commit>
の部分は<commit>..<commit>
とも書けます。この形式の場合は片側の<commit>
を省略可能です。省略された<commit>
はHEAD
として扱われます。
HEAD を一つ前のコミットと比較
git diff HEAD^ HEAD
git diff HEAD^..
ブランチとリモートトラッキングブランチの比較
リモートレポジトリ上のブランチをgit pull
する前に差分を確認するには以下のようにします。
git remote origin # originの最新版を取得
git diff master origin/master # origin上のmasterとローカルのmasterの比較
git merge
: コミットのマージ
Git を代表とする DVCS ではコミットは簡単に分岐していくので、それをマージする処理が非常に頻繁に行われます。Git で2つ以上のコミットをマージするにはgit merge
を使います。
git merge <commit>
git merge <commit>
を実行すると現在のブランチに<commit>
が指すコミットがマージされます。例えば下のようなコミット履歴があり、現在のブランチがmaster
だとしましょう。
A---B---C topic
/
D---E---F---G master
ここでgit merge topic
を実行すると、マージコミットH
が作成されて最終的に以下のような履歴グラフが作成されます。
A---B---C topic
/ \
D---E---F---G---H master
git merge topic
はブランチtopic
が指しているコミットC
を現在のブランチmaster
にマージするコマンドなので、実行後もtopic
変わらずC
を指し続けます。
ちなみにgit merge
は<commit>
を複数与え、3つ以上のコミットを1つのコミットにマージすることも可能です。3つ以上のコミットのマージはあまり使わない気がしますが。
A---B---C topic
/
D---E---F---G master
\
I---J---K dev
この状態で master で git merge topic dev
するとC
, G
, K
がマージされたH
ができます。3つ以上のコミットのマージはoctopus
(タコ)と呼ばれデフォルトでは衝突が起こらない場合のみ実行することができます。
A---B---C topic
/ \
D---E---F---G---H master
\ /
I---J---K topic
git merge
: 衝突の解消
git merge
でマージしようとしている2つのコミットが共通するファイルの同じ部分を編集していると、衝突(conflict)が発生します。
$ git merge topic
Auto-merging members.txt
CONFLICT (content): Merge conflict in members.txtAutomatic merge failed; fix conflicts and then commit the result.
マージの状態を確認する
どのファイルで衝突が発生したのかはgit status
で確認します。Unmerged paths:
の部分にマージに失敗しているファイルが列挙されます。
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: hello.txt
no changes added to commit (use "git add" and/or "git commit -a")
衝突を解決する
git merge
に表示された変更が衝突しているファイルを開くと、
<<<<<<< HEAD
現在のブランチでの変更
=======
マージする対象のブランチでの変更
>>>>>>>
のように衝突が表示されるので好きなエディタを使って、衝突部分を修正します。修正が終わったらファイルをgit add
してステージングします。
git add hello.txt
片側のコミットでファイルが削除されている場合には git merge
, git status
で以下のようなメッセージが表示されます
$ git merge bob
CONFLICT (modify/delete): members.txt deleted…
$ git status
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
deleted by them: hello.txt
そして片側で編集されたファイルがローカルに存在する状態になるので、ファイルを残すのであればgit add
, ファイルを削除するのであればgit rm (--cached)
を実行してインデックスに対して明示的にファイルを追加するか削除するかします。
すべてのファイルの衝突が解決できたらgit commit
を実行してマージコミットをコミットします。コミットメッセージは自動生成されるので-m
などは渡す必要はありません。
git commit
ちなみにUnmerged paths
がある状態でgit commit
を実行しても Committing is not possible because you have unmerged files.という警告が表示され何も行われません。また最後のgit commit
はgit merge --continue
でも代用できます。
マージを中止する
衝突の解消が難しく、一旦git merge
処理を中止したい場合にはgit merge --abort
を実行します。--abort
するとgit merge
実行前の状態に戻ります。
git merge --abort
マージ中なのかを確認する・どのコミットとマージ中なのかを再確認する
マージの解消は時間が手間のかかる処理なので後回しにしてしまって、後になって現在のレポジトリがマージ作業中だったのか分からなくなることがたまにあります。あるいはどのコミットとマージしている最中だったのかが分からなくなることもあります。
このような場合には、.git/MERGE_HEAD
ファイルをチェックします。マージ中の場合にはファイルが存在し、ファイルの中にマージしようとしているコミットの hex が書かれています。
cat .git/MERGE_HEAD
git branch
: ブランチの操作
Git ではブランチの操作は表示に関わるコマンドはgit branch
に集約されています。
ブランチ一覧表示
git branch -vv
git branch
はレポジトリ内に存在するブランチの名前を一覧表示します。現在のブランチの先頭には*
が表示されます。
-vv
をつけることで、各ブランチがどのコミットを指しているかと、どのリモート上のブランチと紐づけられているか(トラッキングブランチ)も合わせて表示されています。
新しいブランチを作る
現在のHEAD
を起点として新しいブランチを作成します。
git branch <branch>
<branch>
の後ろにコミットを指定するとHEAD
以外のコミットを起点としてブランチを作ることもできます。
ブランチを切り替える
ブランチの切り替えは、git checkout <branch>
で行います。ブランチに関わる操作ではあるがコマンドはbranch
ではないので注意。
$ git checkout dev
Switched to branch 'dev'
git checkout <branch>
はローカルにコミットしていない変更などがあるときはerror: Your local changes to the following files would be overwritten by checkout:というエラーが表示されて失敗します。
前述したようにgit checkout
はファイルパスと共に実行すると、指定したファイルを元の状態に戻すコマンドです。2つの大きく違う機能がcheckout
コマンドに集約されているので注意してください。
ブランチを作成して、切り替える
checkout -b
でブランチ作成 → 切り替えの2つの操作を一度に行うことができます。HEAD
を起点とする場合にはコミット前のファイルがあっても動作します。
git checkout -b <branch> # HEADを起点
git checkout <commit> -b <branch> # <commit>を起点
ブランチを削除する
git branch -d <branch>
- 現在のブランチは削除できません
-d
はブランチが他のブランチにマージされている場合のみブランチを削除します。- マージされていないブランチを強制的に削除するには
-D
を指定します。
リモートのブランチを削除する
リモートレポジトリからブランチを削除するにはgit pushを使います。
git push origin --delete <branch_name>
あるいは
git push origin :<branch_name>
詳細はGit でローカル・リモートのブランチを削除する方法 (git branch -d)を参考にしてください。
git remote
: リモートの操作
リモートブランチやリモートトラッキングブランチの操作にはgit remote
やgit fetch
を使用します。
リモートリポジトリの登録
git remote add <name> <URL>
リモートレポジトリの一覧
git remote -v
リモートレポジトリの詳細情報
git remote show <name>
remote show
でリモートレポジトリの URL, リモートトランキングブランチ、現在のレポジトリ上のトラッキングブランチなどが表示されます。
$ git remote show origin
* remote origin
Fetch URL: https://github.com/git/git.git
Push URL: https://github.com/git/git.git
HEAD branch: master
Remote branches:
maint tracked
master tracked
next tracked
pu tracked
todo tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
git fetch/pull
: リモートからコミットを読み込む
リモートレポジトリの最新の状態を取得
git fetch <remote>
<name>
の代わりに--all
を指定すると全てのリモートレポジトリからfetch
が行われるます。
最新の状態を取得してマージする
git fetch
でリモートのコミットを取得しそれをgit merge
でローカルのブランチにマージする処理は非常によく行われるので、専用のコマンドgit pull
が用意されています。
git pull <remote> <src>
<remote> <src>
の部分はよく省略されます。省略された場合の挙動についてはこちらを参照してください。
git pull origin master [~/src/git] Google
From https://github.com/git/git
* branch master -> FETCH_HEAD
Already up to date.
git push
: リモートにコミットを書き込む
パッチ(patch)処理
コミットを取り消す
以前行ったコミットを取り消すにはgit revert
を利用します。git revert
はあるコミットと逆のファイル操作を行うコミットを新たに作成することで以前のコミットによる編集を相殺します。
git revert <commit>
<commit>
は<from>..<to>
のように範囲指定もできます。
チェリーピック
他のブランチ上のコミットを現在のブランチにも適用する「チェリーピック」(つまみ食い)するにはgit cherry-pick
を使用します。
git cherry-pick <commit>
cherry-pick
はrevert
と似たコマンドで同じオプションが使用できます。コミットを逆再生して適用するのがrevert
、順再生して適用するのがcherry-pick
です。
歴史の書き換え
git rebase
などのコマンドを使ってコミットの履歴をあとから書き換えることができます。詳しくはGit -Book 歴史の書き換え(英語版: Rewriting History)を参考にしてください。
直前のコミットを修正する
前述したように、git commit
した直後に間違いがあることに気がついて修正を行う時には、git commit --amend
を使用します。
git commit --amend
git rebase
git rebase <upstream>
「現在のブランチと<upstream>
の共通の親」から「現在のブランチ」までのコミットを<upstream>
にリベースします。
A---B---C topic (HEAD)
/
D---E---F---G master
この状態でgit rebase master
を実行すると
A'--B'--C' topic
/
D---E---F---G master
このような状態になります。
git rebase <upstream> <branch>
現在のブランチではなく<branch>
を<upstream>
にリベースします。git checkout <branch>
が自動で行われます。
git rebase --onto <newbase> <upstream> <branch>
<upstream>
ではなく<newbase>
を起点としてリベースします。
o---o---o---o---o master
\
o---o---o---o---o next
\
o---o---o topic
この状態に対して、git rebase --onto master next topic
を実行すると
o---o---o---o---o master
| \
| o'--o'--o' topic
\
o---o---o---o---o next
となります。
git rebase
: インタラクティブモード
git rebase
に-i
を渡すとインタラクティブモードになり、歴史を修正して複数のコミットをまとめたり(squash)逆に一つのコミットを複数に分割したり(split)できます。詳しくはGit -Book 歴史の書き換え(英語版: Rewriting History)を参考にしてください。
混乱しやすいコマンド
reset と checkout
git reset
とgit checkout
はかなり似た機能を提供するためよく混乱します。きちんと使い分けられるように違いを整理して記憶しておくとよいでしょう。
公式のGit - リセットコマンド詳説(英語: Reset Demystified)も参考にしてください。
パスを指定しない場合
git checkout <commit>
git reset [--soft|--mixed|--hard] <commit>
git reset
はHEAD
だけでなくHEAD
が指している現在のブランチも一緒に移動する(ブランチの強制移動)。git checkout
はHEAD
だけが移動するので、HEAD
が指しているブランチが変わる(ブランチの切り替え)。-
reset --hard
とcheckout
はどちらも作業ディレクトリとインデックスを<commit>
の状態にリセットするという点では非常に似ている。- ただし
checkout
はブランチ切り替えのための日常的にしようする「安全な」コマンド。作業ディレクトリにコミット前の編集がある場合は中断する。 reset --hard
はブランチを強制移動する「危険な」コマンド。作業ディレクトリに編集中のファイルがあっても強制的にリセットされる。
- ただし
パスを指定した場合
git reset [<commit>] [--] <path>
git checkout [<commit>] [--] <path>
パスが指定された場合はどちらのコマンドもHEAD
やブランチに対する操作は行いません。<path>
に指定されたファイルを<commit>
(省略時はHEAD
)から復元します。2つのコマンドの違いは
checkout
はインデックスとワーキングツリーの両方に<commit>
から復元する。reset
はインデックスのみにファイルを<commit>
から復元する。<commit>
はデフォルト値はreset
はインデックス、checkout
はHEAD
その他
ファイルの一部をステージング・コミットする
git add
する際に、-e
を渡すとエディタが起動し、ファイルの一部だけをステージングすることができます。
git add -p
で同様のことがターミナル上でインタラクティブに行えます。-p
の画面でe
を選択すると-e
と同じモードになります。
詳しくはGit Tools - Interactive Stagingを参照してください。
git add -p
, -e
はトラックされていないファイルには使えません。新しいファイルの一部をgit add
したい場合には、まずgit add -N
でファイルをトラックしてからgit add -p
あるいは-e
を実行してください。