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.
This is all still in my local repo.
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-treeto generate a singlenewbranchcontaining 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 wereHEAD@{49}. Then, try this script, replacing thehead -50withhead -<n + 1>, whatever that is in your case:This is grabbing your reflog’s commit history once, then iterating over it, generating
reflog_$ibranches 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 executesgit checkouton the branches, runs the test suite, and shows greens the whole way. Remember,reflog_1represents the most current history;reflog_<n+1>the oldest.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.
Putting all commits on the same branch using
git read-treeFirst, 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 tosed. You must use it or something like it, lest the reflog apply tonewbranchin reverse chronological order. There’s surely a way to do this without using bothawkandsed, but this works:The final result will be
newbranch, which should contain all the commits betweenHEAD@{0}andHEAD@{n}, based upon commitHEAD@{n+1}.