シーン別 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

コミットしていない変更を一時避難する

git stach [push]

stashした変更を一覧表示

git stash list

stashした変更を復元

git stash pop [<stash>]

コミット

ステージングされたファイルをコミットとして記録する。-m <message>でコミットメッセージを指定。

git commit [-m <message>]

直前のコミットを修正する

git commit --amend

履歴の表示

コミットログを表示

git log

コミットログをグラフで表示

git log --graph --oneline

git logで変更内容の表示する

git log -p

git logで著者でコミットをフィルター

git log --author=<pattern>

git logで表示件数を制限

git log -n <number>

差分の表示

ワーキングツリーをインデックスと比較

git diff

ワーキングツリーをHEADと比較する

git diff HEAD

インデックスをHEADと比較する

git diff --cached HEAD

2つのコミットを比較

git diff <base> <target>

コミットのマージ

現在のブランチを<commit>とマージ

git merge <commit>

マージを中断する

git merge --abort

ブランチの操作

ブランチ一覧表示

git branch -vv

新しいブランチを作る

git branch <new>

ブランチを切り替える

git checkout <branch>

ブランチを作成して、切り替える

git checkout [<commit>] -b <branch>

ブランチを削除する

git branch -d <branch>

ブランチを強制的に削除する

git branch -D <branch>

詳細解説

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 checkoutgit 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 commitgit 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>を起点

ブランチを削除する

ブランチを削除するには-dオプションを使用します。

git branch -d <branch>
  • 現在のブランチは削除できません
  • -dはブランチが他のブランチにマージされている場合のみブランチを削除します。
  • マージされていないブランチを強制的に削除するには-Dを指定します。

git remote: リモートの操作

リモートブランチやリモートトラッキングブランチの操作にはgit remotegit 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-pickrevertと似たコマンドで同じオプションが使用できます。コミットを逆再生して適用するのが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 resetgit checkoutはかなり似た機能を提供するためよく混乱します。きちんと使い分けられるように違いを整理して記憶しておくとよいでしょう。 公式のGit - リセットコマンド詳説(英語: Reset Demystified)も参考にしてください。

パスを指定しない場合

git checkout <commit>
git reset [--soft|--mixed|--hard] <commit>
  • git resetHEADだけでなくHEADが指している現在のブランチも一緒に移動する(ブランチの強制移動)。
  • git checkoutHEADだけが移動するので、HEADが指しているブランチが変わる(ブランチの切り替え)。
  • reset --hardcheckoutはどちらも作業ディレクトリとインデックスを<commit>の状態にリセットするという点では非常に似ている。

    • ただしcheckoutはブランチ切り替えのための日常的にしようする「安全な」コマンド。作業ディレクトリにコミット前の編集がある場合は中断する。
    • reset --hardはブランチを強制移動する「危険な」コマンド。作業ディレクトリに編集中のファイルがあっても強制的にリセットされる。

パスを指定した場合

git reset [<commit>] [--] <path>
git checkout [<commit>] [--] <path>

パスが指定された場合はどちらのコマンドもHEADやブランチに対する操作は行いません。<path>に指定されたファイルを<commit>(省略時はHEAD)から復元します。2つのコマンドの違いは

  • checkoutはインデックスとワーキングツリーの両方に<commit>から復元する。
  • resetはインデックスのみにファイルを<commit>から復元する。
  • <commit>はデフォルト値はresetはインデックス、checkoutHEAD
最終更新: 6/25/2019