よもやま話β版

よもやま話を書きます。内容はぺらぺら。自由に書く。

Gitでブランチの歴史改変をするときの流れ備忘録

自分は作業中は超適当にcommitを積み重ねることもしばしばあり、ブランチの内容が完成形になった後、本流にmergeする直前に歴史改変をしておく派。現時点でやっている方法をメモしておく。もちろん、今後もっとこうしようという考えが変わることはありうる。

次のようなfeatureブランチが生えているものとする。

$ git log --oneline --all
8b73f05 (HEAD -> feature) 歴史3
44a692b 歴史2
3f12709 歴史1
def9ac2 (main) first commit

バックアップをとる

チキンハートの持ち主なので、何かmergeが事故ったときのことを常に想像している。 切り戻せるようにバックアップのブランチを作っておく。

$ git branch feature_backup
$ git log --oneline
8b73f05 (HEAD -> feature, feature_backup) 歴史3
44a692b 歴史2
3f12709 歴史1
def9ac2 (main) first commit

コミットを全部溶かす

git reset --mixed で適当な歴史を全部溶かす。バックアップもあるのでえいやでやる。 適当な歴史はHEADから3件存在するので次のようにする。 ※ --mixedは省略可能らしいが、手が慣れてしまって毎回うっかり書いてしまう。

$ git reset --mixed HEAD~3
$ git log --oneline --all
8b73f05 (feature_backup) 歴史3
44a692b 歴史2
3f12709 歴史1
def9ac2 (HEAD -> feature, main) first commit

$ git status
On branch feature
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   hello.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    test1.txt
    test2.txt
    test3.txt

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

$ git status すると歴史が溶けて変更内容だらけになっていることがわかる。カオス。

正史を積みなおす

丁寧にする場合、積みたい歴史単位で $ git add ファイル名 しては commit 、を繰り返す。 (※面倒になったら1つのPullRequestで1機能、と判断して1commitで済ませることもまああるが...。)

$ git add test*.txt
$ git status
On branch feature
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    new file:   test1.txt
    new file:   test2.txt
    new file:   test3.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   hello.txt

$ git commit -m 'test#{N}.txtを生成した'

また、この時「同じファイルの中に複数行の変更があって、それぞれ別のcommitに積みたい」という場合は $ git add -p ファイル名 することで、commitする行を選ぶことができる。

方法はこちら: git-scm.com 7.2 Git のさまざまなツール - 対話的なステージング

終わったら --force-with-lease で強制push

すでにリモートリポジトリにブランチがある場合、念の為 --force-with-lease を使ってpush する。 万が一、他の人がcommitを追加していた時は気づくことができる。

完全に終わったら不要なブランチは消す

そういえば feature_backup というブランチを作っていた。 完全にもう大丈夫と思えたら潔く消す。

$ git branch -D feature_backup

自分はGitを積み木みたいなイメージで毎度使っている。 便利。