10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

git rebaseのeditで過去のリビジョンを変更する

Last updated at Posted at 2019-07-28

git rebase -isquashrewordはよく使っているが、editもなんとなくわかったのでメモ。
具体例として「ファイルをあるリビジョンから別のRev.に移動する」、「リビジョンを分離する」の例を示す。

git rebae の edit の動き

リビジョン(以降Rev.)が下記のようにあるとする(上ほど古い)。

aaa1111
bbb2222
ccc3333
ddd4444
eee5555 ← HEAD

この状態から Rev.bbb2222 と Rev.ddd4444 を変更したい場合、git rebase -iで次のように bbb2222 と ddd4444 のコマンドを e(またはedit)と変更する。

pick aaa1111 change a
e bbb2222 chnage b
pick ccc3333 chnage c
e ddd4444 chnage d
pick eee5555 change e

すると、まず e と変更したRev.のうち、一番古い Rev.bbb2222 が コミットされた直後の状態となる(HEADが Rev.bbb2222を指している)。

aaa1111
bbb2222 ← HEAD

コミット直後の状態なので、modifiedなファイルもstagedなファイルもない。

リビジョンの変更の方法

ここから変更内容によって以下のように操作する。

新たなファイルの追加する場合

Rev.bbb2222 に含まれていないファイルをaddしてcommit --amendする。

  1. git add <追加するファイル>
  2. git commit --amend

変更対象Rev.に含まれているファイルを再編集する場合

Rev.bbb2222 に含まれているファイルを変更し、addしてcommit --amendする。

  1. ファイルを編集する。
  2. git add <編集したファイル>
  3. git commit --amend

変更対象Rev.からファイルを除外する場合

reset @^で1つ前のRev.に戻る。そして除外するファイル以外をaddしてコミットする。

  1. git reset @^
  2. git add <Rev.に残すファイル>
  3. git commit

modifiedのまま残っているファイルは、以下のように処理する。
・変更を捨てるならcheckoutする。
・直後に別なRev.としてコミットするならaddしてcommitする。
・もっと先のRev.で使うなら一旦stashする。

rebase --continue

Rev.bbb2222 に対する編集が終わったら git rebase --continue を実行する。
すると次の変更対象Rev.の Rev.ddd4444 に移動する(HEADが Rev.ddd4444 を指すようになる)。
Rev.ddd4444の変更が終わって git rebase --continue を実行すると、git rebase が完了する。

具体例として

y.into@pc01 MINGW64 /c/git_test (master)
$ git log --oneline --name-status -4
41f8473 (HEAD -> master) change d
M       d1.txt
M       d2.txt
d07aa72 change c
M       c1.txt
f721de1 change b
M       b1.txt
M       b2.txt
1109412 change a
M       a1.txt
M       a2.txt
M       c2.txt

という状態から次の変更を git rebase で行う。

  • Rev.1109412 "change a" に含まている c2.txt の変更を Rev.d07aa72 "chanage c" に移す。
  • Rev.f721de1 "change b" を2つのRev.に分割する。

環境は Windows10、Git for Windows、gitbash。


まず、git rebase -i @~4 を実行する。

pick 1109412 change a
pick f721de1 change b
pick d07aa72 change c
pick 41f8473 change d

# Rebase 1544237..41f8473 onto 41f8473 (4 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
<以下略>

変更対象のRev.1109412、f721de1、d07aa72 のコマンドを "e"(=edit)と変更する。

e 1109412 change a
e f721de1 change b
e d07aa72 change c
pick 41f8473 change d

viを終了すると、最初の変更対象Rev.である Rev.1109412 をコミットした直後の状態となる(HEADが Rev.1109412 を指している)。

y.into@pc01 MINGW64 /c/git_test (master)
$ git rebase -i @~4
Stopped at 1109412...  change a
You can amend the commit now, with

  git commit --amend

Once you are satisfied with your changes, run

  git rebase --continue

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git status
interactive rebase in progress; onto 1544237
Last command done (1 command done):
   edit 1109412 change a
Next commands to do (3 remaining commands):
   edit f721de1 change b
   edit d07aa72 change c
  (use "git rebase --edit-todo" to view and edit)
You are currently editing a commit while rebasing branch 'master' on '1544237'.
  (use "git commit --amend" to amend the current commit)
  (use "git rebase --continue" once you are satisfied with your changes)

nothing to commit, working tree clean

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git log --oneline --name-status -1
1109412 (HEAD) change a
M       a1.txt
M       a2.txt
M       c2.txt

reset で1つ前のRev.に戻し、残したい変更だけaddしてcommitする。

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git reset @^
Unstaged changes after reset:
M       a1.txt
M       a2.txt
M       c2.txt

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git status
interactive rebase in progress; onto 1544237
Last command done (1 command done):
   edit 1109412 change a
Next commands to do (3 remaining commands):
   edit f721de1 change b
   edit d07aa72 change c
  (use "git rebase --edit-todo" to view and edit)
You are currently splitting a commit while rebasing branch 'master' on '1544237'.
  (Once your working directory is clean, run "git rebase --continue")

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

        modified:   a1.txt
        modified:   a2.txt
        modified:   c2.txt

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

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git add a1.txt a2.txt

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git commit -m 'change a'
[detached HEAD dcd363b] change a
 2 files changed, 2 insertions(+)

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git log --oneline --name-status -1
dcd363b (HEAD) change a
M       a1.txt
M       a2.txt

残されたmodifiedな c2.txt は後のRev.に追加するのでstashで退避しておく。

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git status
interactive rebase in progress; onto 1544237
Last command done (1 command done):
   edit 1109412 change a
Next commands to do (3 remaining commands):
   edit f721de1 change b
   edit d07aa72 change c
  (use "git rebase --edit-todo" to view and edit)
You are currently splitting a commit while rebasing branch 'master' on '1544237'.
  (Once your working directory is clean, run "git rebase --continue")

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

        modified:   c2.txt

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

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git stash push
Saved working directory and index state WIP on (no branch): dcd363b change a

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git status
interactive rebase in progress; onto 1544237
<省略>

nothing to commit, working tree clean

最初の変更対象Rev.の操作は終わったので、git rebase --continue で次の変更対象Rev.まで進む。

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 1/4)
$ git rebase --continue
Stopped at f721de1...  change b
You can amend the commit now, with

  git commit --amend

Once you are satisfied with your changes, run

  git rebase --continue

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 2/4)
$ git status
interactive rebase in progress; onto 1544237
Last commands done (2 commands done):
   edit 1109412 change a
   edit f721de1 change b
Next commands to do (2 remaining commands):
   edit d07aa72 change c
   pick 41f8473 change d
  (use "git rebase --edit-todo" to view and edit)
You are currently editing a commit while rebasing branch 'master' on '1544237'.
  (use "git commit --amend" to amend the current commit)
  (use "git rebase --continue" once you are satisfied with your changes)

nothing to commit, working tree clean

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 2/4)
$ git log --oneline --name-status -1
207e142 (HEAD) change b
M       b1.txt
M       b2.txt

第2の変更対象である Rev. は2個に分割する。
resetで1つ前のRev.に戻した後、2つのファイルをそれぞれ別々にコミットする。

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 2/4)
$ git reset @^
Unstaged changes after reset:
M       b1.txt
M       b2.txt

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 2/4)
$ git status
interactive rebase in progress; onto 1544237
Last commands done (2 commands done):
   edit 1109412 change a
   edit f721de1 change b
Next commands to do (2 remaining commands):
   edit d07aa72 change c
   pick 41f8473 change d
  (use "git rebase --edit-todo" to view and edit)
You are currently splitting a commit while rebasing branch 'master' on '1544237'.
  (Once your working directory is clean, run "git rebase --continue")

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

        modified:   b1.txt
        modified:   b2.txt

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

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 2/4)
$ git add b1.txt

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 2/4)
$ git commit -m 'change b1'
[detached HEAD b23ff21] change b1
 1 file changed, 1 insertion(+)

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 2/4)
$ git add b2.txt

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 2/4)
$ git commit -m 'change b2'
[detached HEAD fb3874d] change b2
 1 file changed, 1 insertion(+)

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 2/4)
$ git log --oneline --name-status -2
fb3874d (HEAD) change b2
M       b2.txt
b23ff21 change b1
M       b1.txt

第2の変更対象Rev.の操作も終わったので、git rebase --continueで最後の変更対象Rev.に進む。

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 2/4)
$ git rebase --continue
Stopped at d07aa72...  change c
You can amend the commit now, with

  git commit --amend

Once you are satisfied with your changes, run

  git rebase --continue

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 3/4)
$ git status
interactive rebase in progress; onto 1544237
Last commands done (3 commands done):
   edit f721de1 change b
   edit d07aa72 change c
  (see more in file .git/rebase-merge/done)
Next command to do (1 remaining command):
   pick 41f8473 change d
  (use "git rebase --edit-todo" to view and edit)
You are currently editing a commit while rebasing branch 'master' on '1544237'.
  (use "git commit --amend" to amend the current commit)
  (use "git rebase --continue" once you are satisfied with your changes)

nothing to commit, working tree clean

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 3/4)
$ git log --oneline --name-status -1
41567ce (HEAD) change c
M       c1.txt

Rev.89f04bc "change c" に Rev.9b59dca "change a" から取り除いた c2.txt を追加する。
stashから取り出してaddしてcommit --amendする。

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 3/4)
$ git stash pop
interactive rebase in progress; onto 1544237
Last commands done (3 commands done):
   edit f721de1 change b
   edit d07aa72 change c
  (see more in file .git/rebase-merge/done)
Next command to do (1 remaining command):
   pick 41f8473 change d
  (use "git rebase --edit-todo" to view and edit)
You are currently splitting a commit while rebasing branch 'master' on '1544237'.
  (Once your working directory is clean, run "git rebase --continue")

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

        modified:   c2.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (28cf2135c67665f5ca212664692fd66ad8a5d050)

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 3/4)
$ git status
interactive rebase in progress; onto 1544237
Last commands done (3 commands done):
   edit f721de1 change b
   edit d07aa72 change c
  (see more in file .git/rebase-merge/done)
Next command to do (1 remaining command):
   pick 41f8473 change d
  (use "git rebase --edit-todo" to view and edit)
You are currently splitting a commit while rebasing branch 'master' on '1544237'.
  (Once your working directory is clean, run "git rebase --continue")

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

        modified:   c2.txt

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

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 3/4)
$ git add c2.txt

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 3/4)
$ git commit --amend --no-edit
[detached HEAD 90c4996] change c
 Date: Sun Jul 28 20:44:25 2019 +0900
 2 files changed, 2 insertions(+)

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 3/4)
$ git log --oneline --name-status -1
90c4996 (HEAD) change c
M       c1.txt
M       c2.txt

3つのRev.の変更が終わったので最後の git rebase --continue で作業完了。
下記のgit logの結果にあるようにRev.の変更がなされた。

y.into@pc01 MINGW64 /c/git_test (master|REBASE-i 3/4)
$ git rebase --continue
Successfully rebased and updated refs/heads/master.

y.into@pc01 MINGW64 /c/git_test (master)
$ git log --oneline --name-status -5
5043827 (HEAD -> master) change d
M       d1.txt
M       d2.txt
90c4996 change c
M       c1.txt
M       c2.txt
fb3874d change b2
M       b2.txt
b23ff21 change b1
M       b1.txt
dcd363b change a
M       a1.txt
M       a2.txt
10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?