0

I accidentally did git commit --amend instead of git commit -c ORIG_HEAD after a git reset HEAD~ (as seen on the answer "Undo a commit and redo"), and as a result I seem to have a branched timeline. (I don't know the correct term.) Also, GitHub is showing the amended commit with a timestamp of when I made the amendment, not the original commit.

That is to say, I get this from git log --graph --all:

* commit eea7f50e03fe35013b4f8c31f99b392b90406d3c
| Author: Author <name@example.com>
| Date:   Wed Jan 26 19:42:00 2022 +0000
|
|     Commit made after mistake
|
* commit de775e988b88453ce13eb874c19f29d878e7b0f9
| Author: Author <name@example.com>
| Date:   Wed Oct 19 20:37:02 2016 +0000
|
|     Penultimate old commit
|
| * commit 9c419983e4554803ee9b61b0d45661de8dd1297f
| | Author: Author <name@example.com>
| | Date:   Wed Oct 19 20:38:01 2016 +0000
| |
| |     Final old commit
| |
| * commit f5212efa5b2149a00541e0bf67de9f9995817c47
|/  Author: Author <name@example.com>
|   Date:   Wed Oct 19 20:37:02 2016 +0000
|
|       Penultimate old commit
|
* commit b42e879cd92f3b7b7038546413859e4f9f9497d4
| Author: Author <name@example.com>
| Date:   Mon Aug 24 23:49:22 2015 +0000
|
|     Even older commit
|

What do I need to do to:

  • Correctly amend "Penultimate old commit" with the contents of "Final old commit", maintaining its original timestamp;
  • Get rid of the newer copy of "Penultimate old commit";
  • Have the latest commit follow on from it?
Scott Martin
  • 1,260
  • 2
  • 17
  • 27
  • Can you use `git rebase -i b42e879c`? – user3840170 Jan 26 '22 at 21:15
  • And then? I need a bit more to go on than that. – Scott Martin Jan 26 '22 at 21:19
  • 1
    An amendment *is* a new commit, not an editing of an existing commit. Commits are immutable. – chepner Jan 26 '22 at 21:24
  • 1
    Remove the `pick` line for the duplicate commit, insert `pick 9c419983` for the commit you want. Save and exit the editor. Verify your new history with `git log -p`. (I assume you’re on the branch with `eea7f50e`.) – user3840170 Jan 26 '22 at 21:36
  • 1
    @chepner Then it shouldn't be called "amend", because a thing that's immutable can't be amended. This is low-level nit-picking that doesn't help. – Scott Martin Jan 26 '22 at 22:10
  • @user3840170 I don't understand your suggestion. There's only a main branch in this repository. Why do you want me to pick that commit? What happens to `f5212efa` which I wanted to amend? – Scott Martin Jan 26 '22 at 22:19
  • @ScottMartin: I agree that it shouldn't be called `--amend`. Unfortunately it is, so you need to know that it doesn't: that's why you got the weird result you got. There are two branches in this repository, even if there's only one branch *name* (although if there's only one branch name you should not see the above from `git log --all`: curiously, there are no decorations here, even though decorate is the default for terminal output). – torek Jan 27 '22 at 09:47
  • In any case, rebase probably is the command you want, but it's hard to be more specific. If you edit your output to include the decorations you'll get if you add `--decorate`, it should be easier to be more specific. – torek Jan 27 '22 at 09:48
  • Hi @torek, thanks. I see, the documentation says that `--amend` "Replace[s] the tip of the current branch by creating a new commit." By "decorations" do you mean `(HEAD -> main, origin/main)`? That was already shown on the most recent commit, which wasn't included in my excerpt from the log. – Scott Martin Jan 27 '22 at 13:12
  • @ScottMartin Once you understand that commits are immutable and indestructible, despite the existence of amend and rebase, your understanding of Git will undergo a revolution – matt Jan 27 '22 at 17:43
  • 1
    Here https://stackoverflow.com/questions/55997481/git-remove-all-commits-on-branch-between-merge-points you can see me utterly befuddled due to a situation similar to yours, back in the bad old days before I understood what Git really is – matt Jan 27 '22 at 17:46
  • 1
    Yes, those `HEAD -> main, origin/main` in parentheses are the decorations. Git *finds* commits via these names, so it's important to know where the names are. The *names* are moveable (each name contains one hash ID), while the commits themselves are immutable, so we make new and improved commits (with different hash IDs) that form new and improved chains as shown by `--graph`, then move the names around so that we find the new commits instead of the old ones. To find the nameless branch, Git must have had *some* name—probably not a *branch* name, but some name nonetheless. – torek Jan 28 '22 at 00:41

1 Answers1

0

I sort of understand what happened now although not why. I fixed it as follows:

git rebase -i HEAD~5

Got rid of the listed commits and told it to kill the ones on the right-hand-side branch:

drop 9c41998
drop f5212ef

After that the left-hand-side nameless branch with the commits I wanted to keep was shown as existing upstream in my client - I'd already pushed before noticing this problem. It seems that my amendment had caused the local branch to diverge after the amending. Why the original branch part didn't go up with the push, I don't know. I never use git log usually so its output wasn't clear to me while looking into this.

I did a git pull and that merged the rogue branch with main. The amended commit was still showing up with a committer date of yesterday instead of its original date, so I got rid of that with this:

git rebase --committer-date-is-author-date b42e879

Force push back to upstream, all done.

Scott Martin
  • 1,260
  • 2
  • 17
  • 27