-
-
Notifications
You must be signed in to change notification settings - Fork 90
Workflow: Editing an old commit's contents
Sometimes, you may want to edit the contents of an existing commit. For example, if you're working on a commit stack, and you received code review feedback on a previous commit, then you may want to update it.
Suppose for this article that we're working on C in the following commit graph, and we want to update A:
$ git sl
⋮
◇ e6adfe90 19s (main) Main branch commit
┃
◯ 2d070a71 14s A
┃
◯ 7ebf9885 14s B
┃
● 32d90336 14s (feature) C
The easiest approach is to check out the commit directly, and then amend it:
$ git checkout 2d070a71
# do some work...
$ git commit --amend
...
branchless: This operation abandoned 1 commit!
branchless: Consider running one of the following:
branchless: - git restack: re-apply the abandoned commits/branches
branchless: (this is most likely what you want to do)
branchless: - git smartlog: assess the situation
branchless: - git hide [<commit>...]: hide the commits from the smartlog
branchless: - git undo: undo the operation
branchless: - git config branchless.restack.warnAbandoned false: suppress this message
...
Since you've updated a commit earlier in the stack, its descendant commits were abandoned:
$ git sl
⋮
◇ e6adfe90 2m (main) Main branch commit
┣━┓
┃ ✕ 2d070a71 2m (rewritten as dc95606b) A
┃ ┃
┃ ◯ 7ebf9885 2m B
┃ ┃
┃ ◯ 32d90336 2m (feature) C
┃
● dc95606b 42s A
To fix this, run git restack
:
$ git restack
$ git sl
⋮
◇ e6adfe90 3m (main) Main branch commit
┃
● dc95606b 1m A
┃
◯ 14722c98 3s B
┃
◯ 1c5eba43 3s (feature) C
If you don't want to immediately amend the original commit (for example, if you're not immediately sure that your change addresses the feedback), then you may want to make an additional child commit instead:
$ git checkout 2d070a71
# do some work...
$ git commit
Now your graph will look like this:
$ git sl
⋮
◇ e6adfe90 6m (main) Main branch commit
┃
◯ 2d070a71 6m A
┣━┓
┃ ◯ 7ebf9885 6m B
┃ ┃
┃ ◯ 32d90336 6m (feature) C
┃
● ca7323c7 3s temp: address feedback
Once you've confirmed that this commit is suitable, you can combine it into its parent commit with git rebase -i
:
$ git rebase -i main
The default rebase plan will look like this:
pick 2d070a7 A
pick ca7323c temp: address feedback
Change the second pick
to fixup
:
pick 2d070a7 A
fixup ca7323c temp: address feedback
Then execute the rebase:
...
branchless: This operation abandoned 1 commit!
branchless: Consider running one of the following:
branchless: - git restack: re-apply the abandoned commits/branches
branchless: (this is most likely what you want to do)
branchless: - git smartlog: assess the situation
branchless: - git hide [<commit>...]: hide the commits from the smartlog
branchless: - git undo: undo the operation
branchless: - git config branchless.restack.warnAbandoned false: suppress this message
Successfully rebased and updated detached HEAD.
...
Like the previous case, this results in the descendant commits being abandoned:
⋮
◇ e6adfe90 8m (main) Main branch commit
┣━┓
┃ ✕ 2d070a71 8m (rewritten as 8b8b6ee3) A
┃ ┃
┃ ◯ 7ebf9885 8m B
┃ ┃
┃ ◯ 32d90336 8m (feature) C
┃
● 8b8b6ee3 40s A
So we can fix it with git restack
:
$ git restack
$ git sl
⋮
◇ e6adfe90 9m (main) Main branch commit
┃
● 8b8b6ee3 1m A
┃
◯ 6ddb67d6 1s B
┃
◯ 8ffc6f49 1s (feature) C
If you don't want to check out commit A
, and you know that you can make a patch on top of your current commit C
without it conflicting with either of B
or C
, then you can make the patch and commute (change the order of) the patch upwards in the stack. You might want to do this e.g. if you have build artifacts which you don't want to invalidate.
Detach from the branch you have checked out (if any) and then make your commit:
$ git checkout --detach
$ git commit
$ git sl
⋮
◇ e6adfe90 14m (main) Main branch commit
┃
◯ 2d070a71 14m A
┃
◯ 7ebf9885 14m B
┃
◯ 32d90336 14m (feature) C
┃
● 21753de2 1s temp: address feedback for A
Next, run git rebase -i
to see this rebase plan:
$ git rebase -i main
...
pick 2d070a7 A
pick 7ebf988 B
pick 32d9033 C
pick 21753de temp: address feedback for A
Move the last line to immediately after the first line, and change it to fixup
:
pick 2d070a7 A
fixup 21753de temp: address feedback for A
pick 7ebf988 B
pick 32d9033 C
Then execute the rebase plan. Note that if your patch conflicts with B
or C
, then you'll have to resolve merge conflicts as a part of this step.
...
branchless: This operation abandoned 1 branch (feature)!
branchless: Consider running one of the following:
branchless: - git restack: re-apply the abandoned commits/branches
branchless: (this is most likely what you want to do)
branchless: - git smartlog: assess the situation
branchless: - git hide [<commit>...]: hide the commits from the smartlog
branchless: - git undo: undo the operation
branchless: - git config branchless.restack.warnAbandoned false: suppress this message
Successfully rebased and updated detached HEAD.
The branch feature
was abandoned:
$ git sl
⋮
◇ e6adfe90 16m (main) Main branch commit
┣━┓
┃ ✕ 2d070a71 16m (rewritten as d4919de2) A
┃ ┃
┃ ✕ 7ebf9885 16m (rewritten as 902205ea) B
┃ ┃
┃ ✕ 32d90336 16m (rewritten as 394cdfb2) (feature) C
┃
◯ d4919de2 34s A
┃
◯ 902205ea 34s B
┃
● 394cdfb2 34s C
So run git restack
to fix it:
$ git sl
⋮
◇ e6adfe90 16m (main) Main branch commit
┃
◯ d4919de2 49s A
┃
◯ 902205ea 49s B
┃
● 394cdfb2 49s (feature) C
- Search the Wiki 🔎
- User guide
- Welcome
- Installation
- Tutorial
- Command overview
- General:
- Navigation:
- Committing:
- Rebasing:
- Verification:
- Collaboration:
- Workflows
- Advanced topics
- Reference
- Developer guide
- Onboarding offer
- Development
- Reference