DE version is available. Content is displayed in original English for accuracy.
Advertisement
Advertisement
⚡ Community Insights
Discussion Sentiment
67% Positive
Analyzed from 4553 words in the discussion.
Trending Topics
#git#rebase#commit#commits#history#using#still#conflicts#changes#squash

Discussion (134 Comments)Read Original on HackerNews
I do still find myself tripping up on whether the next appropriate step is to make a commit or continue the rebase, as that is dependent on if you're in a merge conflict or just editing a commit. But even when I get that wrong, and collapse two commits together, abort saves the day.
https://www.man7.org/linux/man-pages/man7/gitrevisions.7.htm...
that means my hashes or their hashes or them keeping my hashes, I am never sure
I think I know what happens in principle (each step of a rebase does a merge of the commit from the list with the last rebased commit) but it's still often hard to understand which side of the conflict represents what, and what would be the desired outcome for that step in the history. So I tend to abort the rebase when I get a conflict and see if I can plan it differently so I can get it through without conflicts.
What I found good to know is that only actions that modify the actual changes in the history - reordering, deleting or editing commits - can cause conflicts. The other actions - reword, fixup or squash - only modify how the changes are grouped into commits and cannot cause conflicts.
So I usually do an interactive rebase in several passes: First a rebase that only reorders commits (or rarely does deletes or edits) and where I deal with the resulting conflicts, then a second pass for fixup or squash operations that can then use the reordered history from the first pass.
Rewords are both harmless and don't require any particular ordering, so can be done in any pass.
Are you using diff3/zdiff3? I ask because you seem to be describing exactly the problem it solves, or at least the way I try to sell people on it.
Basically in addition to 'current' & 'incoming from the rebase' hunks you get 'parent commit of incoming from the rebase' – which allows you to see 'what was I trying to change', i.e. how does the intent of it apply to the different thing that's now on master (whatever I'm reading onto).
1. Abort rebase.
2. Squash all my commits into a single commit.
3. Rebase on target branch again.
The biggest mistake most sources make when teaching about history rewriting is omitting these two lessons first:
- it’s easy to lose uncommitted data in Git and hard to lose committed data
- given this, learn how to use ‘git reflog’ to see what you’ve done and how to undo/redo it (as this post recommends but, even then, a little too late)
If you just get in the habit of constant committing and checking reflog: you’ll never lose data.
(Related lesson from my 10 years employed by GitHub: they almost never do the git gc you’d expect to remove commits so once you push a commit: it’s likely there forever and identifiable by that same hash from anywhere in the fork network. This can be bad/scary so be aware).
Oh wow. Is there a way to trigger GC manually?
For git. You can run `git maintenance run` or the legacy command `git gc`.
in case you are not aware of it already:
https://www.aikido.dev/blog/the-fork-awakens-why-githubs-inv...
Git was written with Linux in mind, where curating a clean commit history is more important than the code itself and warrants the extra hassle.
An actually usable rebase would probably require something like a meta history. But then the meta history would accumulate fixup "commits" and typos in commit messages so the OCD people will want to change that and we're back to square one. In practice, the two times per decade it actually makes business sense to dig through the history to find when a bug was introduced instead of just writing the 5-line fix, you can live with a couple of imperfect commits and merges.
Plus you can always take a note of the commit hash before you do anything crazy. But reflog means you don't have to.
Git really does have all the features you need. I wouldn't argue with anyone complaining about the UI to get there. But it's all in there somewhere.
Git rebase has such foundational data structures and concepts that you couldn't pass a serious college programming course without grokking it.
The only reason someone would be scared of git rebase is:
You probably shouldn't have engineers like that on your team.You do your development and use rebase to organise your code into logical commits/patches that can each be reviewed separately. This way when you do your review in github or on the mailing list or whatever you can review each logical change by going through and reviewing the commits separately (which you can do in github by selecting the commit in the dropdown for the review window).
And of course via email based workflows or "stacked patchset" workflows like what tangled provides then you can get deltas between revisions so that you can see what changed in a given commit between rev 1 and rev 2 so that you don't have to re-review the entire patchset/PR, only the stuff that matters (but still broken up into logical changes).
You’re very incorrect.
That's it. That basic knowledge will carry you far, and will be useful a decade from now. Those are the three best afternoons you can spend. Do it out of respect for the computer.
switch and restore replaced checkout. history is being developed to replace rebase for most common use cases. maintenance replaces gc. etc.
- I find it uninteresting. My version control needs are very simple.
- Most teams I have been in use a small subset of it.
- It's confusing terms and inconsistent cli are huge warning signs to not go down that rabbithole. Today instead of learning Git I read some Tony Hoare, much better.
I've been at once place where they rebased, and it was awful. Complete waste of time. (great place otherwise though)
I guess a keyboard auto corrected i into I.
Here's a GIF I found with Google: https://yogwang.site/2025/cursor-vscode-gitlens-rebase-edito...
I also use git absorb (https://github.com/tummychow/git-absorb) and lazygit a lot (https://github.com/jesseduffield/lazygit).
I'm really not fond of having to `git rebase --interactive` just to drop all commits that are "already in master", especially when I forget this silly step and get a borked rebase.
https://www.man7.org/linux/man-pages/man7/gitrevisions.7.htm...
get ahead at work? split into commits and make it look like multiple days of work
work on your own IP during work hours? edit the timestamp to be outside work hours (i even have a script for this)
1. Everyone uses feature branches
2. Everyone cleans up their branch using interactive rebase on top of main before review
3. All merges have been freshly rebase on main
I think it works very well and keeps the history clean while preserving "each commit does one thing".
The one time I suggested that, someone immediately came up to me trying to convince me that rebases are the most dangerous thing ever.
one of the first things i do in a new gitlab repo is set up ff+squash commit merges with the squash commit message template automatically pulling the MR title, link, description, authors etc.
git log --first-parent
git bisect --first-parent
tbf, this says a lot more about the code base, my colleagues and the shitty, lazy culture at our company that leads to ZERO ownership and architecture ;)
Imagine bushwhacking your way through a bunch of conflicts while rebasing on main... Now you realized that you needed to do some other work before your pr is ready for review... Now you need to rebase on main again and get to relive conflict hell again.
Maybe I'm one of the stupid incompetent people referred to in this post but I haven't figured out a way to deal with the having to solve the same merge conflicts when I rebase again :(
especially since if you are rebasing you may want to rebase your changes from one branch to another (i.e. move to top of main or from on top of one feature to another).
So instead you can just do git rebase --autosquash -i last-good or just git rebase --autosquash and let it squash it down for you.
It isn't particularly fast, but it uses bisect to find the first commit on the target branch that conflicts with your branch, then let's you rebase to that commit. You then repeat the process until you are caught up.
The idea is that solving one conflict many times is usually quite easy, especially if you know the conflicting commit messages, but solving many conflicts in one go is not so easy. This was inspired by me rebasing a 6 month old branch which refactored a file that happened to have many edits in between.
I have a simple rule where if the rebase cannot be solved within a few commit rewrites that I will restart the branch from latest master.
If you are suffering from really difficult rebase scenarios, it's likely that the senior developers are more at fault than the junior developers. The way you organize work over the codebase has the biggest impact on how things would conflict. If nothing ever does, rebasing is a trivial operation.
- create an empty commit with the branch name, type, ticket number etc. (with a small git script, `git issue 321 fix some things` -> `git switch -c 321-fix-some-things && git commit -m "fix(321): some things" --allow-empty`)
- `rebase -i` then shines when you have stacked commits where previous one have been merged _in a changed form (e.g. squashed)_. In such cases git often duplicates the already merged commits thinking they are part of your branch leading to endless dump conflicts, with a "marker" commit you can easily spot it in the `rebase -i` view and then also easily stripp them out by removing their lines
- git rebase -i <commit-hash>^
- select edit
- git reset --soft HEAD~
- make some changes
- git add . && git commit -m "changes"
- git rebase --continue
- Am I using git rebase wrong?
My preference, however, is creating a fixup commit and using rebase to squash it into the old one.
Edit: A sibling comment mentioned "git history fixup" which I'll have to try out.
Again, though, I still use a visual tool.
The opposite is true, of course, for example: you move commits arround, start to resolve conflicts, and after a few steps you realize you can't, so when you
> you can bail out at any time. as aforementioned with git rebase --abort
Yep, except for all the work you've done resolving the conflict, that's "aborted"
> the old commits still exist in git’s object database, unreferenced but intact,
The best UI there is - some hidded data store you're, of course, intimately familiar with, so won't have any trouble getting data out of. Oh, wait, you didn't even know it existed? Tough luck, git gud to avoid data loss!
> botched rebase is a few minutes of you perusing through the reflog.
Unless, of course, your not that sharp to remember all the commits from their names and would also like to see the diff contents to connect to your code work. But that's just more minutes extra, not that big of a loss.
> there’s of course, the low-tech insurance policy: git branch backup-before-rebase
Finally some sensible advice, one that should be the default backup plan to save userst he trouble of wasting "few minutes" perusing the logs
Besides interactive rebase, my other favorite command is “git log —-oneline origin/master..HEAD”
It shows me exactly where I am…
[0] https://ohshitgit.com/
Zero rebases since Fable 5.
Sure, if they want to they can later use `npm -g i` or whatever abomination they want but when we teach them, we should use full arguments, not aliases. please, people :(
TLDR; `jj edit <what_to_edit>; $EDITOR` will update a commit in the middle of the branch
I know you can do this from within magit as well but I've never gotten into that workflow.
it's the one clear tool that i used all the time. moving to jj, it has lots of amazing tools starting with `jj edit` to go change the past safely & conveniently, with much less pain. but i miss the direct powerful data-driven experience of seeing the timeline in a text file, and picking what to do with it. sometimes.
imo every dev should work to get some competency with git rebase! it's an amazing tool. there's few other systems that give such direct control. it's top layer is, perhaps, the excel of version control?