zlacker

[return to "Stacked Diffs with git rebase —onto"]
1. ptx+sif[view] [source] 2025-12-05 15:15:34
>>flexdi+(OP)
What I would really like is a Git equivalent to Mercurial's "fold" operation. I usually make a bunch of commits as I work, just as checkpoints, which I then want to turn into a single final commit when it's done, which could be quite some time later, e.g. "started on thing", "broke it", "broke it more", "Add thing to improve foo of bar".

Mercurial's "histedit" command offers two operations to combine the commits: "fold" and "roll", where "fold" brings the earlier commit into the later commit and "roll" does the reverse. The "fold" operation does exactly what I want in this case: It brings all the changes into the final commit from when I actually finished it, using the commit date of that commit.

Git's "rebase -i" command offers "squash" and "fixup" and "fixup -c" and "fixup -C", but they all do the same thing as "roll", i.e. they keep the earliest commit's date, the date when I started working on the thing and not the date when I finished working on it. (So I then cut and paste the correct date and update the commit afterwards. This may not be the best way to do it.)

◧◩
2. WorldM+aIf[view] [source] 2025-12-05 16:59:43
>>ptx+sif
That is an interesting desire to use a later commit date rather than an earlier one. So many prefer that commit date of when an effort started.

One way to accomplish that is to reorder the commmits in `rebase -i`: "pick" the last commit first and squash/fixup the rest after. That can produce some very weird merge conflicts, but it works well more often than you might think, too.

At the very least, you can do your hand editing of the commits during the rebase instead of after by switching the earliest commit from "pick" to "edit" to have the full power to amend the commit before it moves on (with `git rebase --continue` when you are satisfied). (Versus "reword" if you just want to change the commit message only.)

Also, instead of naming commits things like "broke it" and "broke it more" an option is to use `git commit --fixup={previous commit hash}`. That auto-generates a "fixup!" name based on the previous commit and auto-marks it as a fixup if you use the `--autosquash` flag to rebase.

◧◩◪
3. ptx+yeg[view] [source] 2025-12-05 19:18:55
>>WorldM+aIf
I do use fixup commits as well, for fixing small issues discovered after I make the proper commit, and in that case it makes sense to use the date and message of the earlier commit.

But in the case I'm describing, the earlier commits are essentially just temporary snapshots on the way to making a proper commit. Just a more explicit undo history, basically. I usually don't even bother naming them anything as meaningful as "broke it", actually. Maybe most people wouldn't even bother making these commits – or maybe they would if Git supported "fold".

◧◩◪◨
4. WorldM+3qg[view] [source] 2025-12-05 20:16:58
>>ptx+yeg
My pattern in a case like that is often to start a commit named "WIP thing I'm doing" and `commit --amend` each snapshot, updating the commit message as it starts to come together. `commit --amend` is nicer/gentler than `rebase`, most of the time.

Though there are also times I don't mind working in a very dirty worktree and `git add -p` (interactive add that also makes it easy to stage only parts of files) pieces only once they feel complete and start to tell a story. (And in those cases I may use a lot of `git stash -u` and `git stash pop` snapshots, too, especially if I need to switch branches in that worktree.)

◧◩◪◨⬒
5. ptx+7Ag[view] [source] 2025-12-05 21:06:31
>>WorldM+3qg
Hmm, I may have actually solved my problem. I think what I mostly want to do is this, if I'm working on the "feature-1" branch based on "main":

  $ git checkout feature-1
  $ git reset main
  $ git commit -a -C feature-1@{1}
This squashes all the changes and keeps the date and and message of the final commit on the branch.

Weirdly, although the "-c" and "-C" flags for the fixup operations sound like they should correspond to the same flags for "git commit", which grabs the date along with the message from the specified commit, the fixup flags only affect the message and not the date.

It would be nice if it worked the same for rebase as for commit. Then "fixup -C" would essentially correspond to Mercurial's "fold".

[go to top]