元営業WEBエンジニアのアプリ開発日記

営業出身のWEB系エンジニアが気になったものから作ってはメモを残してくブログ

git rebase を怖れない

概要

これまで、git rebaseはマージコミットを残さないのでよくない(どこで問題が起きたかわからなくなる)。 という理由で無邪気にgit mergeしていたが、 プルリクのサイズがでかくなると、ファイルの差分(変更点)だけでレビューするのがだいぶ苦しくなってくるなぁ。という壁にぶつかったのでgit rebaseコマンドを練習してみる

よくあるケース

コミット履歴を綺麗にする

とりあえずこんな感じのコミット作っといて実験してみよー

$ git log --oneline
7d95cfa (HEAD -> feature/from) fourth comment
4947e58 third comment
fd622a7 second comment
6996fbe first comment
a741ac4 add new line
0b34183 (origin/master, origin/HEAD, master, develop) Initial commit

コミットコメント書き換えたいなー

4つ分のコミットを対象にする

git rebase -i HEAD~4

vim画面が表示されたらpickrに変更して:wqで保存

pick 6996fbe first comment
r fd622a7 second comment
pick 4947e58 third comment
r 7d95cfa fourth comment

# Rebase a741ac4..7d95cfa onto a741ac4 (4 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

rに変更した分だけvimが表示されるので変更したいコメントに変更&保存

2nd comment

# Please enter the commit message for your changes. Lines starting

名前変わってる!

$ git log --oneline                                     25f8fb9 (HEAD -> feature/from) 4th comment
00f97ee third comment
d36ca5b 2nd comment
6996fbe first comment
a741ac4 add new line
0b34183 (origin/master, origin/HEAD, master, develop) Initial commit

コミットをまとめたい

順番入れ替えたり、sでコミットを統合したりして見る
上のコミット(前のコミット)に統合される

pick 6996fbe first comment
pick 25f8fb9 4th comment
s d36ca5b 2nd comment
pick 00f97ee third comment

# Rebase a741ac4..25f8fb9 onto a741ac4 (4 commands)

リベース中に衝突起きちゃうとパニック

vim画面で:wq保存すると。。。でた!このごちゃごちゃ言ってくるやつ

Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not apply 25f8fb9... 4th comment

Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

Could not apply 25f8fb9... 4th comment

とりあえずgit statusして見るのだ

$ git status                                                                                                                    [feature/from|rebase-i]
interactive rebase in progress; onto a741ac4
Last commands done (2 commands done):
   pick 6996fbe first comment
   pick 25f8fb9 4th comment
Next commands to do (2 remaining commands):
   squash d36ca5b 2nd comment
   pick 00f97ee third comment
  (use "git rebase --edit-todo" to view and edit)
You are currently rebasing branch 'feature/from' on 'a741ac4'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

    both modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

git rebase --abortするともとに戻せる。これまではパニックになってこれで逃げてた気がするw
git diff打ってみると、うむぅ。やはりコンフリクトしてる。直して見よう。

$ git diff
++<<<<<<< HEAD
 +azcdefghijklmnopqrstu
++=======
+ awcdefghijklmnopqrstu
++>>>>>>> 25f8fb9... 4th comment

git rebase --continueしろって言ってたなぁ。。

$ git rebase --continue
README.md: needs merge
You must edit all merge conflicts and then
mark them as resolved using git add

怒られた。git addするのね。。

$ git add README.md
$ git rebase --continue
[detached HEAD 8e03aea] new 2nd comment
 1 file changed, 1 insertion(+), 1 deletion(-)
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not apply d36ca5b... 2nd comment

Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

Could not apply d36ca5b... 2nd comment

まだ出る!!!これぶつかり続けてる限り出るのねきっと

$ git log --oneline
fc3b535 (HEAD -> feature/from) third comment
40b3699 new 3nd comment
6996fbe first comment
a741ac4 add new line
0b34183 (origin/master, origin/HEAD, master, develop) Initial commit

conflictしてるものを直し続けたら ちょっと意図した通りにはならなかったけど、順番変わってくっついた!!

間違って埋め込んだ修正を直したい

修正したいコミットのpickeに変更して保存

$ # third commentのコミットを変更したい
$ git log --oneline
7d95cfa (HEAD -> feature/from) fourth comment
4947e58 third comment
fd622a7 second comment
6996fbe first comment
a741ac4 add new line
0b34183 (origin/master, origin/HEAD, master, develop) Initial commit
$ git show 4947e58
-aycdefghijklmnopqrstu
+axcdefghijklmnopqrstu
$
$ # 恒例のrebase -i
$ git rebase -i HEAD~4
pick a741ac4 add new line
pick 6996fbe first comment
e 40b3699 new 3nd comment
pick fc3b535 third comment

# Rebase 0b34183..fc3b535 onto 0b34183 (4 commands)

あとは修正したいファイルを修正してgit add && git rebase --continueすればよろしく変更される!

$ git log --oneline 
091a7c4 (HEAD -> feature/from) fourth comment
e2411bb third comment
fd622a7 second comment
6996fbe first comment
a741ac4 add new line
$
$ git show e2411bb
-aycdefghijklmnopqrstu
+alcdefghijklmnopqrstu

途中のコミット変更したことでconflictしちゃうこともあるけど、上で書いた通り解消してgit add && git rebase --continueしとけばよろしく変わってる

リモートにプッシュしたけどrebaseして綺麗にしたい!!!

共同で開発してるブランチじゃやっちゃいけないだろうけど。
自分専用で開発してるブランチを綺麗にしたい時とかにしたい。

$ git log --oneline
091a7c4 (HEAD -> feature/from, origin/feature/from) fourth comment
e2411bb third comment
fd622a7 second comment
6996fbe first comment
a741ac4 add new line
0b34183 (origin/master, origin/HEAD, master, develop) Initial commit
$
$ git rebase -i HEAD~4
[detached HEAD 04e3b85] 3rd comment
 Date: Tue Jan 1 09:45:00 2019 +0900
 1 file changed, 1 insertion(+), 1 deletion(-)
Successfully rebased and updated refs/heads/feature/from.
$
$ git branch -vv
  develop      0b34183 Initial commit
* feature/from 011984f [origin/feature/from: ahead 2, behind 2] fourth comment
  master       0b34183 [origin/master] Initial commit
$
$ git push origin                                                                                                                        [feature/from]
To ssh://github.com/shintaro123/practice_docker.git
 ! [rejected]        feature/from -> feature/from (non-fast-forward)
error: failed to push some refs to 'ssh://git@github.com/shintaro123/practice_docker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
$
$ git push origin -f                                                                 Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 564 bytes | 564.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To ssh://github.com/shintaro123/practice_docker.git
 + 091a7c4...011984f feature/from -> feature/from (forced update)
$ 
$ git log --oneline                                                                 
011984f (HEAD -> feature/from, origin/feature/from) fourth comment
04e3b85 3rd comment
fd622a7 second comment
6996fbe first comment
a741ac4 add new line
0b34183 (origin/master, origin/HEAD, master, develop) Initial commit

rebaseするとコミット自体作り変えてしまうので、push時に怒られちゃう。
なので-fつけるとよろし

ブランチの派生元間違えてた

間違えてブランチ派生させてたら、付け替えれる

$ git log --graph --all                                                             * commit 1daf0829120078db7e1e21703b3dee3e9489824c (HEAD -> feature/1)
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 11:54:32 2019 +0900
|
|     6th comment
|
* commit 7ce16217a2626ae5de96ff3c679a5cf61a996061
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 11:52:53 2019 +0900
|
|     5th comment
|
* commit 011984f0d0b69c23ee5c49daeae60a21b60021f8 (origin/feature/from, feature/from)
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 09:50:37 2019 +0900
|
|     fourth comment
|
* commit 6996fbe6155a4646581a1a755e0d4994ac2857fa
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 09:43:41 2019 +0900
|
|     first comment
|
* commit a741ac4af34810b19c5b803488242789d634dead
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 09:42:30 2019 +0900
|
|     add new line
|
* commit 0b34183461640d118a4cb92cb1a0ad810da34844 (origin/master, origin/HEAD, master, develop)
  Author: Shintaro <shintaro.0112@gmail.com>
  Date:   Mon Dec 31 21:22:03 2018 +0900

      Initial commit
$
$ git rebase --onto develop feature/from feature/1                                   First, rewinding head to replay your work on top of it...
Applying: 5th comment
Using index info to reconstruct a base tree...
M   README.md
Falling back to patching base and 3-way merge...
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: Failed to merge in the changes.
Patch failed at 0001 5th comment
Use 'git am --show-current-patch' to see the failed patch

Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
$
$ # conflictしたら直してgit rebase --continue
$ git log --graph --all                                                             * commit 9791e34f9ff11b58f517835f0db36f72eb150ddc (HEAD -> feature/1)
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 11:54:32 2019 +0900
|
|     6th comment
|
* commit 69e9a35f0978b6cad234f2fb8150b2df2638a268
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 11:52:53 2019 +0900
|
|     5th comment
|
| * commit 011984f0d0b69c23ee5c49daeae60a21b60021f8 (origin/feature/from, feature/from)
| | Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| | Date:   Tue Jan 1 09:50:37 2019 +0900
| |
| |     fourth comment
| |
| * commit a741ac4af34810b19c5b803488242789d634dead
|/  Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
|   Date:   Tue Jan 1 09:42:30 2019 +0900
|
|       add new line
|
* commit 0b34183461640d118a4cb92cb1a0ad810da34844 (origin/master, origin/HEAD, master, develop)
  Author: Shintaro <shintaro.0112@gmail.com>
  Date:   Mon Dec 31 21:22:03 2018 +0900

      Initial commit

もう何もわからない。もとに戻したい

git reflogコマンドを使うと操作履歴が出るので、色々間違っちゃってもこれを頼りにgit reset --har [コミット番号]でもとに戻せる

$ git reflog                                                                         9791e34 (HEAD -> feature/1) HEAD@{0}: rebase finished: returning to refs/heads/feature/1
9791e34 (HEAD -> feature/1) HEAD@{1}: rebase: 6th comment
69e9a35 HEAD@{2}: rebase: 5th comment
0b34183 (origin/master, origin/HEAD, master, develop) HEAD@{3}: rebase: checkout develop
1daf082 HEAD@{4}: commit: 6th comment
7ce1621 HEAD@{5}: commit: 5th comment
011984f (origin/feature/from, feature/from) HEAD@{6}: checkout: moving from feature/from to feature/1
011984f (origin/feature/from, feature/from) HEAD@{7}: rebase -i (finish): returning to refs/heads/feature/from
011984f (origin/feature/from, feature/from) HEAD@{8}: rebase -i (pick): fourth comment
$
$ git log --graph --all                                                                                                                     [feature/1]
* commit 1daf0829120078db7e1e21703b3dee3e9489824c (HEAD -> feature/1)
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 11:54:32 2019 +0900
|
|     6th comment
|
* commit 7ce16217a2626ae5de96ff3c679a5cf61a996061
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 11:52:53 2019 +0900
|
|     5th comment
|
* commit 011984f0d0b69c23ee5c49daeae60a21b60021f8 (origin/feature/from, feature/from)
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 09:50:37 2019 +0900
|
|     fourth comment
|
* commit 6996fbe6155a4646581a1a755e0d4994ac2857fa
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 09:43:41 2019 +0900
|
|     first comment
|
* commit a741ac4af34810b19c5b803488242789d634dead
| Author: Shintaro Uchiyama <shintaro.a.uchiyama@accenture.com>
| Date:   Tue Jan 1 09:42:30 2019 +0900
|
|     add new line
|
* commit 0b34183461640d118a4cb92cb1a0ad810da34844 (origin/master, origin/HEAD, master, develop)
  Author: Shintaro <shintaro.0112@gmail.com>
  Date:   Mon Dec 31 21:22:03 2018 +0900

      Initial commit

派生元の付け替えもなかったことに!!!!!

まとめ

ちょろっと書こうとしたら多くなった。
やはり一度コマンド打つとしっくりくる。これからは実際の開発でもちゃんと使っていこう!!!!