はじめに
今日も同じ作業を行うために調べたので、メモします。
- 作業内容をmaster branch に merge した後、ローカルでmaster branch でそのまま作業してcommit を進めてしまった。
- master branch をもとのコミットまで戻り、作業ブランチを作り、そこに作業分を反映させたい
ということでございます。
方針は単純です。
- 間違って進めてしまった分をpatch として保存する
- master branch でのcommit をさかのぼり、新しいブランチを作る。
- 先に保存したパッチを充てる。
- 間違って進めてしまった master branch のコミットを消す。
動作確認
間違ってmaster branch でコミットを進めてみます。
- 初めに、file001だけがcommit された状態だとします。
$ git log --oneline
* 3e9769f first commit
- その後、file002, file003 をそれぞれmaster branch のまま追加してしまったとします。
$ git add file002
$ git commit -m "file002"
$ git add file003
$ git commit -m "file003"
$ git log --oneline --graph --all
* 3b570c0 (HEAD -> master) file003
* dc5ed63 file002
* 3e9769f first commit
- ここで「しまった。作業ブランチを切って作業するつもりだったのに。。。」と気が付きます。
まず、差分をpatch として保存します。ただの git diff です。こういう設計は素晴らしい!
$ git diff HEAD^^ > tmp.path
戻って作業ブランチを作ります。
$ git checkout HEAD^^
HEAD is now at 3e9769f first commit
$ git checkout -b dev/test
Switched to a new branch 'dev/test'
- すかさずpatch を当てます。
$ patch -p1 < tmp.patch
patching file file002
patching file file003
- ここで本来行いたかったコミットをします。
$ git add file002 file003
$ git commit -m "add file002 and file003"
- ですが、さきほど誤って進めてしまった master branch のcommit が残っている。
$ git log --oneline --graph --all
* c7a2497 (HEAD -> dev/test) file002 file003
| * 3b570c0 (master) file003
| * dc5ed63 file002
|/
* 3e9769f first commit
- 消そう。まず master branch に戻ろう。
$ git checkout master
Previous HEAD position was 3e9769f first commit
Switched to branch 'master'
$ git log --oneline --graph --all
* c7a2497 (dev/test) file002 file003
| * 3b570c0 (HEAD -> master) file003
| * dc5ed63 file002
|/
* 3e9769f first commit
- コミットを消す。というのは、直前のコミットにリセットする、と指示するらしい。
$ git reset --hard dc5ed63
HEAD is now at dc5ed63 file002
$ git log --oneline --graph --all
* c7a2497 (dev/test) file002 file003
| * dc5ed63 (HEAD -> master) file002
|/
* 3e9769f first commit
- 更にもう一度reset すると、問題のcommit は無くなる。
$ git reset --hard HEAD^
HEAD is now at 3e9769f first commit
$ git log --oneline --graph --all
* c7a2497 (dev/test) file002 file003
* 3e9769f (HEAD -> master) first commit
- これで晴れて作業ブランチに戻ろう
$ git checkout dev/test
Switched to branch 'dev/test'
$ ls
file001 file002 file003 tmp.patch
まとめ
所望の作業はこれでできた。
- 実は注意点として、問題のコミットを消すときにはちゃんとmaster branch に戻ることが必要でした。戻らずに git resetを行ったら、新作の作業ブランチと問題のコミットの残るmaster branchが接続されてしまいました。そこのところの仕組みが分かっていませんが、(おい!苦笑)、気を利かせてくれたんだと思います。明示的に一歩一歩消すために、master branch の先頭のcommit から一歩一歩戻りました。
-
git reset --hard
がgit reset --soft
か選択肢がありますが、ここでは、必要な状態は dev/test にすべて保存されているので、作業領域ではhard で消してしまってよい、と考えました。
もっと簡単に行う方法もきっとあるのだと思いますが。まずはこのあたりで。
(2020/10/22)