How to turn a set of amended commits (stored in reflog) into real commits

I was doing a refactoring, and just kept amending every time I made any decent progress. It has gone very well, and I realized it would be nice to be able to show people how I handled such a huge refactoring (lots of tiny steps, just nudging code around, with a green test suite at every point).

The commits are all in my reflog. Is there a way to turn each of those amended commits into its own real commit (sorry, don’t know the terminology) so that users can see each step rather than just the aggregated ones on lines 81 and 57? I don’t need unique messages for the commits or anything, just that they are captured in the history.

  • Hey git, what happened to the last commits?
  • Commit failed error when committing new version to svn repository
  • Delete a specific commit knowing commit id
  • GitHub for Mac - Staging is not working correctly (Changes not staged for commit)
  • git: how to move committed changes from master to branch?
  • git archive from a specific hash from remote
  • This is all still in my local repo.

  • TortoiseGit vs Git Extensions
  • How do I write a batch file which opens the GitBash shell and runs a command in the shell?
  • Git Rebase master conflicts
  • Logging out or deleting credentials from git shell
  • Creating diff patch using netbeans 7.4
  • How to get winmerge to show diff for new file in git?
  • 3 Solutions collect form web for “How to turn a set of amended commits (stored in reflog) into real commits”

    Reconstructing the reflog might not be as difficult as it first appears. You can regenerate the reflog’s commits into distinct branches, or you can use git read-tree to generate a single newbranch containing a portion of the reflog.

    One commit per branch solution:

    Suppose you wanted distinct branches for each commit. First, copy your repository. You’re going to change your reflog in this process, so you might as well use a throwaway version. Second, examine your reflog and find the commit with which you want to start. It’s going to look like HEAD@{n}. Suppose it were HEAD@{49}. Then, try this script, replacing the head -50 with head -<n + 1>, whatever that is in your case:

    reflog=$(git reflog | head -50 | awk '{ print $1 }')
    for ref in $reflog; do
        git checkout -B "reflog_$i" $ref
        i=$(expr $i + 1)

    This is grabbing your reflog’s commit history once, then iterating over it, generating reflog_$i branches along the way. You can cherry-pick, merge, or manipulate them however you want. If this is simply for a presentation, you could write a short script that executes git checkout on the branches, runs the test suite, and shows greens the whole way. Remember, reflog_1 represents the most current history; reflog_<n+1> the oldest.

    for i in $(seq 50 1); do
        git checkout "reflog_$i"

    Throw it up on a projector while you explain your commit method and it’d be a nice backdrop.

    If you want to combine all the branches, you can run this ruby script to apply them in order (or create an equivalent in whatever language you’re comfortable with). Let me reiterate that you should have your directory backed up, because this is rather destructive.

    #!/usr/bin/env ruby
    n = 50
    n.downto 0 do |i|
      system "
        git read-tree reflog_#{i}
        git commit -m 'Refactoring #{n - i}'
        git checkout -- .
        git br -D refog_#{i}

    Putting all commits on the same branch using git read-tree

    First, copy your repository. Then use a script like the one below. Per the discussion in the first solution, change the two <n + 1> to whatever depth you want in your reflog, plus one. Note the additional pipe to sed. You must use it or something like it, lest the reflog apply to newbranch in reverse chronological order. There’s surely a way to do this without using both awk and sed, but this works:

    reflog=$(git reflog | head -<n + 1> | awk '{ print $1 }' | sed -n '1!G;h;$p')
    git checkout -B newbranch HEAD@{<n + 1>}
    for ref in $reflog; do
        git read-tree "$ref"
        git commit --no-verify -m "Adding commit $ref"
        git checkout -- .

    The final result will be newbranch, which should contain all the commits between HEAD@{0} and HEAD@{n}, based upon commit HEAD@{n+1}.

    It’s possible, but likely difficult.

    Every time you did an --amend, you essentially “threw away” the previous commit and replaced it with the new amended commit, which contains the previous changes plus whatever was amended.


    A<--B (master)

    now commit –amend:

    A<--C (master)

    now commit –amend again:

    A<--D (master)

    Commits B and C still exist. However, they’re not pointed to by anything and will eventually be garbage collected.

    So to get the graph you want:

    git checkout master
    git reset --hard A
    git cherry-pick B
    git cherry-pick C
    git cherry-pick D


    A<--B'<--C'<--D' (master)

    (Note the prime (apostrophe) symbol – indicating they are new commits with new hashes)

    Now, the one thing I’m unsure about is whether or not you’ll have conflicts. I believe you will, since each of the later commits contain some of the same changes as the previous commits, given that they were amended. If so, you’ll have to resolve those.

    Keep in mind, given the way git works, if you try this and it doesn’t work, getting back to where you are right now is a simple matter of:

    git reset --hard D

    You could make a new branch out of the first reflog entry, and then for each reflog entry, git checkout the tree to workarea and then commit it.

    This way you shouldn’t get any conflicts, because you are essentially only rewriting the workarea tree with a newer reflog tree.

    Git Baby is a git and github fan, let's start git clone.