gitで誤ったブランチに対して行った変更を正しいブランチへ移す(cherry-pick編)
では一度コミットしてしまった変更を別のブランチへ付け変える方法について紹介しました。
この例では誤ったブランチに対して一度コミットしてしまいましたが、
コミットする前に誤ったブランチで作業していたことに気付くこともよくあります。
例えば以下のような状態です:
$ git branch
master
* topic-y
$ git branch topic-x master
$ $EDITOR # git checkout topic-x を忘れて作業してしまった。
$ git status
# On branch topic-y
# 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: application.source
# modified: library.source
#
no changes added to commit (use "git add" and/or "git commit -a")
一度コミットしていたのであればgit cherry-pick
で対処できますが、
この場合はまだコミットしていません。
どうすればよいでしょうか。
git stash
を使います。具体的には以下の通りです:
$ git status # (1)
# On branch topic-y
# 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: application.source
# modified: library.source
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git stash save
Saved working directory and index state WIP on topic-y: 0100002 Update to use Y
HEAD is now at 0100002 Update to use Y
$ git status # (2)
# On branch master
nothing to commit (working directory clean)
$ git checkout topic-x
Switched to branch 'topic-x'
$ git stash pop # (3)
# On branch topic-x
# 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: application.source
# modified: library.source
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (fffffff000000000000000000000000000000000)
git stash save
を実行すると
まだコミットされていない変更を一旦脇に置いて
作業ディレクトリの内容を何の変更もないクリーンな状態に戻します。
また、git stash pop
を実行すると
先程脇に置いた変更を適用し直すことができます。
これを利用すれば
「まだコミットしていない変更を一旦脇に置いておいて、
正しいブランチに切り替えた後で脇に置いた変更を元に戻す」
という形で
誤ったブランチに対して行った変更を正しいブランチへ移すことができます。
なお、git stash save
で「脇に置いた」変更はスタックのように積まれていきます。git stash pop
では最後に積まれた変更を適用してスタックから取り除いています。
このスタックに積まれている変更は git stash list
で確認することができます。
より詳しくはgit stash
のマニュアルを参照してください。
やろうと思えば以下のコマンドで git stash
と同様のことができます。
ただ面倒なので普通は git stash
を使います。
$ git branch
master
topic-x
* topic-y
$ git status
# On branch topic-y
# 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: application.source
# modified: library.source
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git checkout -b tmp
M application.source
M library.source
Switched to branch 'tmp'
$ git commit -am 'WIP'
$ git checkout topic-x
Switched to branch 'topic-x'
$ git cherry-pick -n tmp
Finished one cherry-pick.
$ git branch -D tmp
Deleted branch tmp (was fffffff).
$ git status
# On branch topic-x
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: application.source
# modified: library.source
#