Gitコマンド入門::rebase(-i,drop,その2,#A)「第十八回」
みなさんこんにちは! 前回は、drop を試していかがでしたか? これで、新しいコミットから削除していくことは、おそらく問題なく出来るようになったと思います。また、2つ、3つと、複数のコミットを同時に削除することも大丈夫ですね。ということで、今日は、途中のコミットを削除すると、どうなるのか? 実際に試して行きたいと思います。
あ、、、あと、ここまで説明してきてなんですが、本家本元のサイトも、よろしければどうぞ!
私も、ちょこちょこ読んでいますが、gitのことを正しく理解することの重要性も感じますし、さらに自分で伝えるときにも、それをうまく取り入れたいと思います。
尚、開発者としての私の資質は、そんなに素晴らしいとも思っていません。たまたま、ゲーム開発に入社する話が21歳のときにあり、アセンブラを使ってゴリゴリソースを書いてから、ここまでやってきただけの事なんですね。やっぱり今時とはスタイルも違うと思いますので、読者の方には、ちょっと申し訳ないのですが、その分、慌てず焦らずに、じっくりと解説して行きたいと考えております。それでは、前置きが長くなりましたけど、さっそく、進めて行きましょう!
前回の記事はこちらです!
前回は、新しいコミットから削除
ハッシュ値 | コメント | README.md | 動作 |
---|---|---|---|
c0f998d | 1st | # rebase | pick |
0fa830d | A | # A | pick |
f8b5ccd | B | # B | pick |
2d138a2 | C | # C | pick |
cb468d1 | D | # D | drop 前回は、最新のコミット |
今回は、A コミットを削除してみましょう!
ハッシュ値 | コメント | README.md | 動作 |
---|---|---|---|
c0f998d | 1st | # rebase | pick |
0fa830d | A | # A | drop 今回は、ここを削除! |
f8b5ccd | B | # B | pick |
2d138a2 | C | # C | pick |
cb468d1 | D | # D | pick |
git rebase -i --root を実行!
$ git rebase -i --root
vi エディターの画面が起動します!
pick c0f998d 1st
drop 0fa830d A // <-- ここを、pick から、drop に変更!
pick f8b5ccd B
pick 2d138a2 C
pick cb468d1 D
# Rebase cb468d1 onto 2d138a2 (5 commands)
// 以下~ 中略
いつものREADME.mdのマージコンフィクト
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not apply f8b5ccd... B
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 f8b5ccd... B
$ cat README.md で内容確認!
$ cat README.md
<<<<<<< HEAD
# rebase
=======
# B
>>>>>>> f8b5ccd... B
A が、dropされて、1stとBのマージでエラー!
ハッシュ値 | コメント | README.md | - |
---|---|---|---|
c0f998d | 1st | # rebase | ここ! |
0fa830d | A | # A | drop削除 |
f8b5ccd | B | # B | ここ! |
2d138a2 | C | # C | - |
cb468d1 | D | # D | - |
現状のステータスも確認してみましょう!
git status
interactive rebase in progress; onto 886efcf
Last commands done (3 commands done):
drop 0fa830d A
pick f8b5ccd B
(see more in file .git/rebase-merge/done)
Next commands to do (2 remaining commands):
pick 2d138a2 C
pick cb468d1 D
(use "git rebase --edit-todo" to view and edit)
You are currently rebasing branch 'main' on '886efcf'.
(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 restore --staged <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")
Google翻訳: $ gitステータス
進行中のインタラクティブなリベース。 886efcfに、最後に実行されたコマンド(3つのコマンドが実行されました):
ドロップ 0fa830dA
f8b5ccdBを選択します
(詳細については、ファイル.git / rebase-merge / doneを参照してください)
次に実行するコマンド(残りの2つのコマンド):
2d138a2Cを選択します
cb468d1Dを選択します
(「gitrebase --edit-todo」を使用して表示および編集します)
現在、ブランチ「main」を「886efcf」にリベースしています。
(競合を修正してから、「git rebase --continue」を実行します)
(このパッチをスキップするには、「git rebase --skip」を使用してください)
(「gitrebase --abort」を使用して元のブランチをチェックアウトします)
こちらのコマンドは、3つの選択肢があります。
- git rebase --continue // README.md の変更を行ったあとで、入力します!
- git rebase --skip // 何もせず、次のrebaseへ進むとき!
- git rebase --abort // 強制終了で、元に戻します。
マージされていないパス:
(「git restore --staged <file> ...」を使用してステージングを解除します)
(「git add <file> ...」を使用して解決をマークします)
両方が変更されました:README.md
コミットに変更が追加されていません(「git add」または「git commit-a」、あるいはその両方を使用)
以下の2つの案内がされていますね。
- restoreコマンドで、README.mdをステージングから作業ディレクトリーコピーするか?
- README.md をマージして、add、commit するか?
それでは、まず最初は、git rebase --abort ですね。
$ git rebase --abort
// とにかく、意図しないことが起こったときは、--abort !
$ git log --oneline --reverse
c0f998d 1st
0fa830d A
f8b5ccd B
2d138a2 C
cb468d1 (HEAD -> main, origin/main) D
$ cat README.md
# D
// はい、元通り!
では、最初からやり直し、git rebase -i --root を実行、そして、git rebase --skip!
$ git rebase -i --root
// vi エディターが起動するので、先ほど同様、
// Aを、pickから、drop に変更して、Esc + wq
$ git rebase --skip
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not apply cb468d1... D
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 cb468d1... D
git rebase --skip
は、何度入力しても、上記の警告文が繰り返し出ます。次は、実際に、README.mdのファイルを編集してみましょう![2]
README.mdのマージ処理!
git restore --staged README.md
$ cat README.md
<<<<<<< HEAD
# rebase
=======
# D
rebase コマンドを実行する前の環境は、HEAD位置が、Dでしたから、ステージングにある、README.mdファイル中身も、当然、"# D" ですね。また、c0f998d 1st との、コンフィクト部分も、すぐさまに判定してくれていますね。
ハッシュ値 | コメント | README.md | 補足解説 |
---|---|---|---|
c0f998d | 1st | # rebase | rebase 実行中のHEADの位置 |
0fa830d | A | # A | drop削除 |
f8b5ccd | B | # B | - |
2d138a2 | C | # C | - |
cb468d1 | D | # D | rebase を実行する前のHEADの位置 |
README.mdの内容が、# D それを、commit --amend します。コミット先は、現在のHAED c0f998d 1st ですね。
$ git add README.md
$ git commit --amend
// viが起動するので、新しいコメントを、1st + D として、Esc + wq
// 保存して終了させます。
// まだ、rebaseの処理が続くかどうかわかりませんが、
// 基本的には、drop するのは、Aのみなのでなにもない筈!
git rebase --continue
// そして、log を見てびっくり! ガビョーン!
$ git log --oneline --reverse
d2987fb (HEAD -> main) 1st + D
ハッシュ値:過去 | コメント | README.md | 補足解説 |
---|---|---|---|
c0f998d | 1st + D | # D | ハッシュ値も、d2987fbとなり、こんな結末に! |
0fa830d | A | # A | dropで削除を指定 |
f8b5ccd | B | # B | gitが自動で削除 |
2d138a2 | C | # C | gitが自動で削除 |
cb468d1 | D | # D | gitが自動で削除 |
README.md のファイルの編集のしかたによっては、このような事態を招くんですよね。
実は、今の私の知識でも、この状態を解説できません。
ただ、言えることは、いつもの、git reset --hard で、簡単に元に戻せること、そして、きっと、これで問題はないのでしょう。つまり自動で履歴をdropしても、README.md以外のファイルにも影響がないから、このような処理を、git側で自動で行ったと思います。おそらく、他のファイルがあった場合は、また、動作が異なると予測していますよ!(笑)
[5]
git reset --hard で元の状態に戻して!// ハッシュ値を検索! コメント文字列は、"commit: D"
$ git reflog | grep "commit: D"
cb468d1 HEAD@{81}: commit: D // 無事、ハッシュ値が分かりましたね!
// ハッシュ値は、cb468d1 を指定して実行!
git reset --hard cb468d1
HEAD is now at cb468d1 D
git log --oneline --reverse
c0f998d 1st
0fa830d A
f8b5ccd B
2d138a2 C
cb468d1 (HEAD -> main, origin/main) D
// はい、無事に元通り!(^^)v
それでは、今回はここまで、お疲れ様でした!
-
README.md のマージの仕方によっては、さらにこのコミットでも、コンフィクトが発生しますので、ご注意ください。 ↩︎
-
skipで、マージ&コンフィクト処理が、B,C,Dと実際は進んでくれます。終了すると、1stのみ、README.mdの中身は、マージしないと、"# rebase" となります。 ↩︎
-
このあたりの動作の理解をイメージできていないと、実践で混乱してくるので、気を付けてください。 ↩︎
-
今回は、gitのrebaseを深堀するためにも、エラーになるケースから進めてみました。恐らく、途中のコミットをdropする使い方は、きっと、レアケースだと思うので無駄になるかもしれませんけどね。(苦笑)まあ~、本来なら、squashあたりがお手軽だと思います。勿論、いまのところの私の感覚ですけどね。 ↩︎
-
実際に指定するハッシュ値は、それぞれの環境で異なります。ハッシュ値の探し方は、
git reflog | grep "commit: D"
で、検索可能です! ↩︎
Discussion