dromodel
dromodel

Reputation: 10203

How can I amend a non-HEAD commit with Git?

I've committed a series of changes to a local topic branch in my Git repository. After each commit, I run a small set of smoke tests to verify the functionality, when possible. Upon running a larger set of tests later before submitting a pull request, I discover some more bugs missed earlier. I could create a new commit for the bug fixes but since it's just a local topic branch I'd like to modify the commits that I already have. There's two ways that I've been doing it:

  1. Make the changes, test them. Stash them and then pop at the appropriate point during rebase -i.
  2. Make a new commit then rebase -i to reorder them and squash it.

If the bug fix happened to be needed in the last commit, then I can commit with --amend to solve the problem. Does Git provide a shortcut to amending parents of HEAD or am I stuck with the current method?

Upvotes: 4

Views: 1113

Answers (3)

Robin Green
Robin Green

Reputation: 33063

There is another way to approach this problem, which is to use TopGit in the following way: Each commit in your topic branch would instead become its own branch (you can use tg import for this when the commits already exist). To edit a commit, you would just switch to its corresponding branch, edit it, git commit it, and then run tg update -a to ripple the changes forward to all the patches that depended on it. Finally, you would run tg export (selecting the appropriate command-line options) to convert your temporary TopGit branches into the final series of revisions.

Upvotes: 2

Mohammad AbuShady
Mohammad AbuShady

Reputation: 42799

You said local branch and I'm going to answer assuming you didn't push any thing yet, otherwise don't do this.

Assuming the commit you want to edit is 'abcdef' you'll run a rebase

git rebase abcdef~ 
# the ~ is needed, you need the parent of the commit you want to edit

Then when your editor starts up, change the commit you want to edit from pick to edit or e, save and close and the HEAD will stop in that place, do whatever changes you want and stage them then do a commit or rebase --continue and the rebase will continue.

Upvotes: 3

poke
poke

Reputation: 387637

Git does not provide shortcuts for amending commits other than the current HEAD. This is because every change of a commit will effectively create a completely new commit object which is incompatible with the one before. That also means that when you were to change the direct parent of HEAD, then HEAD would need to change too. This is not obvious and a destructive action. It’s also very discouraged to edit any commit you have published before.

If you really want to do that, you will have to do an interactive rebase, where the impact is made very clear: Every rebase will create new, incompatible commit objects.

The correct solution would be to keep the history intact as it is, even if there is an error and simply add a new commit which fixes the bug introduced earlier. Git is supposed to respect the history as it was in the project. Just as you identified and fixed that bug actually later, you should also create a commit where you fix that bug later. There is nothing wrong with having non-perfect code as the part of the history. Constantly changing commits from the past would just introduce more problems that you solve with it and is somewhat against the “spirit of source control”.

Upvotes: 6

Related Questions