[HN Gopher] Git Rebase for the Terrified
___________________________________________________________________
Git Rebase for the Terrified
Author : aaronbrethorst
Score : 229 points
Date : 2026-01-07 19:03 UTC (6 days ago)
(HTM) web link (www.brethorsting.com)
(TXT) w3m dump (www.brethorsting.com)
| coffeebeqn wrote:
| I wish rebase was taught as the default - I blame the older
| inferior version control software. It's honestly easier to reason
| about a rebase than a merge since it's so linear.
|
| Understanding of local versus origin branch is also missing or
| mystical to a lot of people and it's what gives you confidence to
| mess around and find things out
| Akranazon wrote:
| The end result of a git rebase is arguably superior. However, I
| don't do it, because the process of running git rebase is a
| complete hassle. git merge is one-shot, whereas git rebase
| replays commits one-by-one.
|
| Replaying commits one-by-one is like a history quiz. It forces
| me to remember what was going on a week ago when I did commit
| #23 out of 45. I'm grateful that git stores that history for me
| when I need it, but I don't want it to force me to interact
| with the history. I've long since expelled it from my brain, so
| that I can focus on the current state of the codebase. "5
| commits ago, did you mean to do that, or can we take this other
| change?" I don't care, I don't want to think about it.
|
| Of course, this issue can be reduced by the "squash first, then
| rebase" approach. Or judicious use of "git commit --amend --no-
| edit" to reduce the number of commits in my branch, therefore
| making the rebase less of a hassle. That's fine. But what if I
| didn't do that? I don't want my tools to judge me for my
| workflow. A user-friendly tool should non-judgmentally
| accommodate whatever convenient workflow I adopted in the past.
|
| Git says, "oops, you screwed up by creating 50 lazy commits,
| now you need to put in 20 minutes figuring out how to cleverly
| combine them into 3 commits, before you can pull from main!"
| then I'm going to respond, "screw you, I will do the next-best
| easier alternative". I don't have time for the judgement.
| teaearlgraycold wrote:
| This seems crazy to me as a self-admitted addict of "git
| commit --amend --no-edit && git push --force-with-lease".
|
| I don't think the tool is judgmental. It's finicky. It
| requires more from its user than most tools do. Including
| bending over to make your workflow compliant with its needs.
| theryan wrote:
| While it is a bit of a pain, it can be made a lot easier with
| the --keep-base option. This article is a great example
| https://adamj.eu/tech/2022/03/25/how-to-squash-and-
| rebase-a-... of how to make rebasing with merge conflicts
| significantly easier. Like you said though, it's not super
| user-friendly but at least there are options out there.
| nicoburns wrote:
| > "oops, you screwed up by creating 50 lazy commits, now you
| need to put in 20 minutes figuring out how to cleverly
| combine them into 3 commits, before you can pull from main!"
|
| You can also just squash them into 1, which will always work
| with no effort.
| DHRicoF wrote:
| Then is not rebase your problem, but all your other
| practices. Long lived feature branches with lot's of
| unorganized commits with low cohesion.
|
| Sometimes it's ok to work like this, but you asking git not
| being judgamental is like saying your roomba should
| accomodate to you didin't asking you to empty it's dust bag.
| PaulDavisThe1st wrote:
| You can make long lived feature branches work with rebase,
| you just have to regularly rebase along the way.
|
| I had a branch that lived for more than a year, ended up
| with 800+ commits on it. I rebased along the way, and the
| predictably the final merge was smooth and easy.
| layer8 wrote:
| I don't see how rebase frequency changes the problem of
| getting conflicts with some random commit within your
| long-lived branch, when doing a rebase.
|
| I rebase often myself, but I don't understand the logic
| here.
| PaulDavisThe1st wrote:
| 1) because git rerere remembers the resolutions to the ..
|
| 2) small conflicts when rebasing the long lived branch on
| the main branch
|
| if instead I delayed any rebasing until the long lived
| branch was done, I'd have no idea of the scale of the
| conflicts, and the task could be very, very different.
|
| Granted, in some cases there would be no or very few
| conflicts, and then both approaches (long-lived branch
| with or without rebases along the way) would be similar.
| layer8 wrote:
| If you do a single rebase at the end, there is nothing to
| remember, you just get the same accumulated conflicts you
| also collectively get with frequent rebases. Hence I
| don't understand the benefit of the latter in terms of
| avoiding conflicts.
| PaulDavisThe1st wrote:
| You don't see a difference between dealing with conflicts
| within a few days of you doing the work that led to them
| (or someone else), and doing them all at once, perhaps
| months later?
| BeetleB wrote:
| > Long lived feature branches
|
| I always do long lived feature branches, and rarely have
| issues. When I hear people complain about it, I question
| their workflow/competence.
|
| Lots of commits is _good_. The thing I liked about
| mercurial is you could squash, while still keeping the
| individual commits. And this is also why I like jj - you
| get to keep the individual commits while eliminating the
| noise it produces.
|
| Lots of commits isn't inherently bad. Git is.
| echelon wrote:
| git rebase squash as a single commit on a single main branch is
| the one true way.
|
| I know a lot of people want to maintain the history of each PR,
| but you won't need it in your VCS.
|
| You should always be able to roll back main to a real state.
| Having incremental commits between two working stages creates
| more confusion during incidents.
|
| If you need to consult the work history of transient commits,
| that can live in your code review software with all the other
| metadata (such as review comments and diagrams/figures) that
| never make it into source control.
| jameshush wrote:
| This is one of the few hills I will die on. After working on
| a team that used Phabricator for a few years and going back
| to GitHub when I joined a new company, it really does make
| life so much nicer to just rebase -> squash -> commit a
| single PR to `main`
| fc417fc802 wrote:
| What was stopping you from squash -> merge -> push two new
| changesets to `main`? Isn't your objection actually to the
| specifics of the workflow that was mandated by your
| employer as opposed to anything inherent to merge itself?
| hnarn wrote:
| I completely agree. It also forces better commit messages,
| because "maintaining the history of each PR" is forced into
| prose written by the person responsible for the code instead
| of hand-waving it away into "just check the commits" -- no
| thanks.
| _flux wrote:
| Merging merge requests as merge commits (rather than fast-
| forwarding them) gives the same granularity in the main
| branch, while preserving the option to have bisect dive
| inside the original MR to actually find the change that made
| the interesting change in behavior.
| yxhuvud wrote:
| I wish github created automation for this flow like they
| have for other variants.
| kunley wrote:
| But they have, with pull requests. When you merge a pull
| request it is done via the "subtree" merge strategt,
| which preserves partial commits and also does not flatten
| them.
| yxhuvud wrote:
| There is no button to rebase, and then merge with a merge
| commit no-ff.
| fc417fc802 wrote:
| > You should always be able to roll back main to a real
| state.
|
| Well there's your problem. Why are you assuming there are
| non-working commits in the history with a merge based
| workflow? If you really need to make an incremental commit at
| a point where the build is broken you can always squash prior
| to merge. There's no reason to conflate "non-working commits"
| and "merge based workflow".
|
| Why go out of the way to obfuscate the pathway the
| development process took? Depending on the complexity of the
| task the merge operation itself can introduce its own bugs as
| incompatible changes to the source get reconciled. It's
| useful to be able to examine each finished feature in
| isolation and then again after the merge.
|
| > with all the other metadata (such as review comments and
| diagrams/figures) that never make it into source control.
|
| I hate that all of that is omitted. It can be invaluable when
| debugging. More generally I personally think the tools we
| have are still extremely subpar compared to what they could
| be.
| Izkata wrote:
| > I know a lot of people want to maintain the history of each
| PR, but you won't need it in your VCS.
|
| Having worked on a maintenance team for years, this is just
| wrong. You don't know what someone will or won't need in the
| future. Those individual commits have had extra context that
| have been a massive help for me all sorts of times.
|
| I'm fine with manually squashing individual "fix typo"-style
| commits, but just squashing the entire branch removes too
| much.
| lanyard-textile wrote:
| Disagree!
|
| If those commits were ready for production, they would have
| been merged. ;)
|
| Don't put a commit on main unless I can roll back to it.
| z3dd wrote:
| When your PR build takes more than an hour you'll think
| twice before creating multiple PRs for multiple related
| commits (e.g. refactoring+feature) when working on a
| single issue.
| eeperson wrote:
| > I know a lot of people want to maintain the history of each
| PR, but you won't need it in your VCS.
|
| I strongly disagree. Losing this discourages swarming on
| issues and makes bisect worse.
|
| > You should always be able to roll back main to a real
| state. Having incremental commits between two working stages
| creates more confusion during incidents.
|
| If you only use merge commits this shouldn't be any more
| difficult. You just need to make sure you specify that you
| want to use the first parent when doing reverts.
| noisem4ker wrote:
| Hard disagreement.
|
| https://0x5.uk/2021/03/15/github-rebase-and-squash-
| considere...
| jillesvangurp wrote:
| Rebase your local history, merge collaborative work. It helps
| to just relabel rebase as "rewrite history". That makes it more
| clear that it's generally not acceptable to force push your
| rewritten history upstream. I've seen people trying to force
| push their changes and overwrite the remote history. If you
| need to force push, you probably messed up. Maybe OK on your
| own pull request branches assuming nobody else is working on
| them. But otherwise a bad idea.
|
| I tend to rebase my unpushed local changes on top of upstream
| changes. That's why rebase exists. So you can rewrite your
| changes on top of upstream changes and keep life simple for
| consumers of your changes when they get merged. It's a courtesy
| to them. When merging upstream changes gets complicated (lots
| of conflicts), falling back to merging gives you more
| flexibility to fix things.
|
| The resulting pull requests might get a bit ugly if you merge a
| lot. One solution is squash merging when you finally merge your
| pull request. This has as the downside that you lose a lot of
| history and context. The other solution is to just accept that
| not all change is linear and that there's nothing wrong with
| merging. I tend to bias to that.
|
| If your changes are substantial, conflict resolution caused by
| your changes tends to be a lot easier for others if they get
| lots of small commits, a few of which may conflict, rather than
| one enormous one that has lots of conflicts. That's a good
| reason to avoid squash merges. Interactive rebasing is
| something I find too tedious to bother with usually. But some
| people really like those. But that can be a good middle ground.
|
| It's not that one is better than the other. It's really about
| how you collaborate with others. These tools exist because in
| large OSS projects, like Linux, where they have to deal with a
| lot of contributions, they want to give contributors the tools
| they need to provide very clean, easy to merge contributions.
| That includes things like rewriting history for clarity and
| ensuring the history is nice and linear.
| cousin_it wrote:
| Maybe I'm old, but I still think a repository should be a
| repository: sitting on a server somewhere, receiving clean
| commits with well written messages, running CI. And a local
| copy should be a local copy: sitting on my machine, allowing
| me to make changes willy-nilly, and then clean them up for
| review and commit. That's just a different set of operations.
| There's no reason a local copy should have the exact same
| implementation as a repository, git made a wrong turn in
| this, let's just admit it.
| fc417fc802 wrote:
| I agree but I think git got the distributed (ie all nodes
| the same) part right. I also think what you say doesn't
| take it far enough.
|
| I think it should be possible to assign different instances
| of the repository different "roles" and have the tooling
| assist with that. For example. A "clean" instance that will
| only ever contain fully working commits and can be used in
| conjunction with production and debugging. And various
| "local" instances - per feature, per developer, or per
| something else - that might be duplicated across any number
| of devices.
|
| You can DIY this using raw git with tags, a bit of
| overhead, and discipline. Or the github "pull" model
| facilitates it well. But either you're doing extra work or
| you're using an external service. It would be nice if
| instead it was natively supported.
|
| This might seem silly and unnecessary but consider how you
| handle security sensitive branches or company internal
| (proprietary) versus FOSS releases. In the latter case
| consider the difficulty of collaborating with the community
| across the divide.
| pamcake wrote:
| > I still think a repository should be a repository:
| sitting on a server somewhere, receiving clean commits with
| well written messages, running CI. And a local copy should
| be a local copy: sitting on my machine, allowing me to make
| changes willy-nilly, and then clean them up for review and
| commit
|
| This is one way to see things and work and git supports
| that workflow. Higher-level tooling tailored for this view
| (like GitHub) is plentiful.
|
| > There's no reason a local copy should have the exact same
| implementation as a repository
|
| ...Except to also support the many git users who are
| different from you and in different context. Bending gits
| API to your preferences would make it less useful, harder
| to use, or not even suitable at all for many others.
|
| > git made a wrong turn in this, let's just admit it.
|
| Nope. I prefer my VCS decentralized and flexible, thank you
| very much. SVN and Perforce are still there for you.
|
| Besides, it's objectively wrong calling it "a wrong turn"
| if you consider the context in which git was born and got
| early traction: Sharing patches over e-mail. That is what
| git was built for. Had it been built your way (first-class
| concepts coupled to p2p email), your workflow would most
| likely not be supported and GitHub would not exist.
|
| If you are really as old as you imply, you are showing your
| lack of history more than your age.
| onraglanroad wrote:
| > And a local copy should be a local copy: sitting on my
| machine, allowing me to make changes willy-nilly, and then
| clean them up for review and commit.
|
| That's exactly what Git is. You have your own local copy
| that you can mess about with and it's only when you sync
| with the remote that anyone else sees it.
| tjpnz wrote:
| I've had recent interns who've struggled with rebase and
| they've never known anything but Git. Never understood why that
| was given they seem ok with basic commits and branching. I
| would agree that rebase is easier to reason about than merging
| yet I'm still needing to give what feels like a class on it.
| recursive wrote:
| The fact that people have a harder time understanding rebase
| is evidence that rebase is harder to reason about. Whether
| you update your understanding based on that evidence is up to
| you. If I have to pick between merge and rebase, I would
| generally pick merge. It seems to cause less conflicts with
| long-lived branches. Commits maintain their identity so each
| one has to be conflict-resolved at most once.
|
| However, even better for me (and my team) is squash on PR
| resolve.
| jghn wrote:
| IMO it's one of those things where rebase is at first less
| intuitive but once you get it is a lot simpler & easier to
| reason about. In contrast merging at first seems more
| straightforward but is actually less so.
|
| that's not a value judgement in either direction, both
| initially simpler and longterm simpler have their merits.
| CJefferson wrote:
| I don't mind rebasing a single commit, but I hate it when
| people rebase a list of commits, because that makes commits
| which never existed before, have probably never been tested,
| and generally never will be.
|
| I've had failures while git bisecting, hitting commits that
| clearly never compiled, because I'm probably the first person
| to ever check them out.
| Marsymars wrote:
| Sometimes it feels like the least-bad alternative.
|
| e.g. I'm currently working on a substantial framework upgrade
| to a project - I've pulled every dependency/blocker out that
| could be done on its own and made separate PRs for them, but
| I'm still left with a number of logically independent commits
| that by their nature will not compile on their own. I could
| squash e.g. "Update core framework", "Fix for new syntax
| rules" and "Update to async methods without locking", but I
| don't know that reviewers and future code readers are better
| served by that.
| wonger_ wrote:
| I wonder how relevant and feasible this workflow would be:
| https://graydon2.dreamwidth.org/1597.html
|
| Where you have two repositories, one "polished" where every
| commit always passes, and another for messier dev history.
| chuckadams wrote:
| It seems to me the "Not Rocket Science" invariant is
| upheld if you just require all PRs to be fast-forward
| changes. Which I guess is an argument in support of
| rebase, but a clean merge counts too. If the test suite
| passes on the PR branch, it'll pass on main, because
| that's what main will _be_ afterward. Ideally you don 't
| even test the same commit hash twice.
|
| If you have expensive e2e tests, then you might want to
| keep a 'latest' tag on main that's only updated when
| those pass.
| capitainenemo wrote:
| In mercurial you could have those in phase hidden for
| future reference. In jujutsu you can have those in a local
| set, but not push upstream. Only unfortunate thing with
| jujutsu is because it is trying to be a git overlay, you
| lose state that a mercurial clone on another machine would
| have.
| eeperson wrote:
| I've heard people say before that it is easier to reason about
| a linear history, but I can't a think of a situation where this
| would let me solve a problem easier. All I can think of is a
| lot of downsides. Can you give an example where it helps?
| jayd16 wrote:
| If this was the main strategy used even for public/shared
| branches, then everyone would have to deal with changing,
| conflicting histories all the time.
| astrobe_ wrote:
| Oh, that's why. I barely used any CVS before Git, so I was
| always puzzled about the "weird" opinions on this topic. I'm
| still puzzled by the fact that some people seem to reject
| entirely the idea of rewriting history - even locally before
| you have pushed/published it anywhere.
|
| Sometimes people look sort of "superstitious" to me about Git.
| I believe this is caused by learning Git through web front-ends
| such as Github, GitLab, Gitea etc., that don't tell you the
| entire truth; desktop GUI clients also let the users only see
| Git through their own, more-or-less narrow "window".
|
| TBH, sometimes Git can behave in ways you don't expect, like
| seeing conflicts when you thought there wouldn't be (but up to
| now never things like choosing the "wrong" version when doing
| merges, something I did fear when I started using it a ~decade
| ago).
|
| However one usually finds an explanation after the fact.
| Something I've learned is that Git is usually right, and
| forcing it to do things is a good recipe to mess things up
| badly.
| bodge5000 wrote:
| Funnily enough in all my years of using git, this thread is the
| first time I've encountered merge. It sounds easier I suppose,
| but I don't really have a problem with rebase and will likely
| just continue as is
| thibaut_barrere wrote:
| PSA: I'm not terrified of rebase, yet it's good to know this:
|
| https://docs.github.com/en/get-started/using-git/about-git-r...
|
| > Warning - Because changing your commit history can make things
| difficult for everyone else using the repository, it's considered
| bad practice to rebase commits when you've already pushed to a
| repository.
|
| A similar warning is in Atlassian docs.
| ongy wrote:
| I think a large part of this is about how a branch is expected
| to be used.
|
| Branches that people are expected to track (i.e. pull from or
| merge into their regularly) should never rebase/force-push.
|
| Branches that are short-lived or only exist to represent some
| state can do so quite often.
| thibaut_barrere wrote:
| It is this, plus more:
|
| - the web tooling must react properly to this (as GH does
| mostly)
|
| - comments done at the commit level are complicated to track
|
| - and given the reach of tools like GH, people shooting their
| own foot with this is (even experienced ones) most likely
| generate a decent level of support for these tools teams
| xlii wrote:
| Also branches that are write-only by a single person by
| consensus. E.g. "personal" PR branches that are not supposed
| to be modified by anyone but owner.
| mr_mitm wrote:
| Is there a reason why that recommendation cannot be changed to
| "don't ever force push unless you are certain no one else has
| fetched this branch"?
| z3dd wrote:
| Well that's a distinction which makes sense in theory but is
| not realistic in practice for most projects with multiple
| contributors.
| PaulDavisThe1st wrote:
| Over at ardour.org, we've never had an issue with this
| practice. Two core full time devs, dozens of others.
| eichin wrote:
| "fetched this branch" needs to include "started reviewing the
| PR", and probably other cases; it does mean switching modes
| for devs who usually rebase privately.
| xlii wrote:
| Allow me (today) to be that person to propose checking out
| Jujutsu instead [0]. Not only it has a superpower of atomic
| commits (reviewers will love you, peers will hate 8 small PRs
| that are chained together ;-)) but it's also more consistent than
| git and works perfectly well as a drop-in replacement.
|
| In fact, I've been using Jujutsu for ~2 years as a drop-in and
| nobody complained (outside of the 8 small PRs chained together).
| Git is great as a backend, but Jujutsu shines as a frontend.
|
| [0]: https://www.jj-vcs.dev/latest/
| vlovich123 wrote:
| How do you handle publishing the stack?
| dcre wrote:
| There's tooling like https://github.com/LucioFranco/jj-spr
| for managing stacks of PRs, but for stacks of 2 or 3 it's not
| too bad to do it manually.
| wocram wrote:
| It depends on what you're publishing to, but works with most
| other tools by using a bookmark for each publish target.
| _flux wrote:
| I think I'd love to use Jujutsu, but I enjoy Magit (for Emacs)
| too much to entertain the thought of switching :/.
|
| Besides, Magit rebasing is also pretty sweet.
| turboponyy wrote:
| Samesies - need a Majjit before I can consider trying it out.
| skulk wrote:
| I used to think like this, but then I realized: jj-mode.el
| exists[0] and you can still use magic since it's still a git
| repo underneath. Seriously, don't let this hold you back.
|
| [0]: https://github.com/bolivier/jj-mode.el
| Zambyte wrote:
| Also been using Jujutsu for about 2 years. I feel like I have
| learned so much about how git actually works by simply not
| using git.
| kps wrote:
| And `jj undo`, so nothing is terrifying.
| mamcx wrote:
| And if a major problem, `jj op log` + `jj op log restore` fix
| it. This is the major super power of jj: Before I need to
| nuke the git repo on bad rebases (not chance in hell I can
| find how undo the massive 20+ steps bad rebase)
| smw wrote:
| I mean `git reflog` is right there! But jj is awesome,
| agreed
| Aperocky wrote:
| well git reflog is that, annoying, yes, but we have LLM so I
| don't actually need to remember how all the command syntax
| exactly like back in 2019.
| darknavi wrote:
| Is git reflog that bad to use? It just lists a bunch of
| commit hashes. Find the one you want and hard reset to it.
| Aperocky wrote:
| It's the one I keep going to LLM for, others like rebase
| are muscle memory at this point.
| mamcx wrote:
| +1
|
| `jj` is the _only_ tool that make me use `rebase` personally.
| Before, I see as the punishment given by my team wishes :)
| grokys wrote:
| Does it support submodules yet? That was the thing that stopped
| me using it last time I checked.
| tcoff91 wrote:
| Submodules are cursed. I feel bad for you that you have to
| work in a repo that uses them.
| bkmq wrote:
| What is the problem with submodules? I like to use them
| because it means the code I need from another repo remains
| the same until I update it. No unexpected breaking changes.
| tcoff91 wrote:
| Using a package manager to share code between repos has
| worked far better for me than submodules.
|
| This comment sums up the issues better than I could:
| https://news.ycombinator.com/item?id=31792396
| steveklabnik wrote:
| Not natively, but you can still use the regular git commands
| to update them, and it works.
| yawaramin wrote:
| > reviewers will love you, peers will hate 8 small PRs that are
| chained together
|
| My peers are my reviewers...
| jon-wood wrote:
| You don't have to chain 8 PRs together, Github tries really
| hard to hide this from you but you can in fact review one
| commit at a time, which means you don't need to have a stack of
| 8 PRs that cascade into each other.
| Liskni_si wrote:
| You do if you find yourself in a team where PRs are squash-
| merged. :-(
| unshavedyak wrote:
| Does that happen on merge or before PR creation? I thought
| the setting only applied it when you hit the merge button,
| so you'd still have commits prior to the merge. Though that
| won't help if someone pre-squashes them :s
| unshavedyak wrote:
| Yup, that's what my team does. It works wonderfully, and it
| fits well with Github's "large PR" mindset imo. It could be a
| bit better in the Github UI, but so can most things. I vastly
| prefer it to individually reviewing tons of PRs.
|
| The funny thing about this debate for me is that i find it
| comes down to the committer. If the committer makes small
| commits in a stacked PR, where each commit is a logical unit
| of work, part of the "story" being told about the overall
| change, then i don't personally find it's that useful to
| stack them. The committer did the hard part, they wrote the
| story of changes in a logical, easy to parse manner.
|
| If the story is a mess, where the commits are huge or out of
| logical order, etc - then it doesn't matter much in my view..
| the PR(s) sucks either way.
|
| I find stacked PRs to be a workflow solution to what to me is
| a UI problem.
| BeetleB wrote:
| The key thing to point out is that jujutsu is a rebase-based
| workflow, and no on who uses jujutsu ever worries about
| rebasing (they may not even be aware of it). It's a good
| demonstration of a tool that got rebase right, unlike git.
|
| Pre-jujutsu, I never rebased unless my team required it. Now I
| do it all the time.
|
| Pre-jj, I never had linear history, unless the team required
| it. Now most of my projects have linear history.
|
| A better UI makes a _huge_ difference.
| nickkell wrote:
| I'm a big fan of rebasing to keep the commit history clean and
| as a form of self-discipline when coding to make sure I'm
| grouping the changes atomically.
|
| I will try to give Jujutsu a go based on your recommendation!
| ngruhn wrote:
| Maintaining linear history is arguably more work. But excessively
| non-linear history can be so confusing to reason over.
|
| Linear history is like reality: One past and many potential
| futures. With non-linear history, your past depends on "where you
| are". ----- M -----+--- P /
| ----- D ---+
|
| Say I'm at commit P (for present). I got married at commit M and
| got a dog at commit D. So I got married first and got a Dog
| later, right? But if I go back in time to commit D where I got
| the dog, our marriage is not in my past anymore?! Now my wife is
| sneezing all the time. Maybe she has a dog allergy. I go back in
| time to commit D but can't reproduce the issue. Guess the dog
| can't be the problem.
| hnarn wrote:
| > So I got married first and got a Dog later, right?
|
| No. In one reality, you got married with no dog, and in another
| reality you got a dog and didn't marry. Then you merged those
| two realities into P.
|
| Going "back in time to commit D" is already incorrect phrasing,
| because you're implying linear history where one does not
| exist. It's more like you're switching to an alternate past.
| ngruhn wrote:
| The point is that it's harder to reason over.
| hnarn wrote:
| I don't really agree that it's harder to reason over in the
| sense that it's hard to understand the consequences, but I
| also agree that a linear history is superior for
| troubleshooting, just like another comment pointed out that
| single squashed commits onto a main branch makes it easier
| to troubleshoot because you go from a working state to a
| non-working state between two commits.
| agumonkey wrote:
| there are others tricky time issues with staging/prod
| parallel branching models too, the most recent merge (to
| prod) contains older content, so time slips .. maybe for
| most people it's obvious but it caused me confusion a few
| times to compare various docker images
| fc417fc802 wrote:
| > the most recent merge (to prod) contains older content
|
| Can't that also happen with a rebase? Isn't it an (all
| too easy to make) error any time you have conflicting
| changes from two different branches that you have to
| resolve? Or have I misunderstood your scenario?
| psychoslave wrote:
| That's also because there are multiple concerned that are tried
| to be presented as the same exposed output through a common
| feature. Having one branch that provides a linear logical
| overview of the project feature progression is not incompatible
| with having many other branches with all kind of messes going
| back and forth, merging and forking each other and so on.
|
| In my experience, when there is a bug, it's often quicker to
| fix it without having a look at the past commits, even when a
| regression occurs. If it's not obvious just looking at the
| current state of the code, asking whoever touch that part last
| will generally give a better shortcut because there is so much
| more in the person mind than the whole git history.
|
| Yes logs and commit history can brings the "haha" insight, and
| in some rare occasion it's nice to have git bisect at hand.
|
| Maybe that's just me, and the pinnacle of best engineers will
| always trust the source tree as most important source of
| information and starting point to move forward. :)
| fc417fc802 wrote:
| You omitted the merge commit. M is taken so let's go with R.
| You jump back to M to confirm that the symptoms really don't
| predate the marriage. Then you jump to R to reproduce and track
| down the underlying cause of the bad interaction.
|
| Had you simply rebased you would have lost the ability to
| separate the initial working implementation of D from the
| modifications required to reconcile it with M (and possibly
| others that predate it). At least, unless you still happen to
| have a copy of your pre-rebase history lying around but I
| prefer not to depend on happenstance.
| ngruhn wrote:
| > Had you simply rebased you would have lost the ability to
| separate the initial working implementation of D from the
| modifications required to reconcile it with M
|
| I'd say: cleaning that up is an advantage. Why keep that
| around? It wouldn't be necessary if there was no update on
| the main branch in the meantime. With rebase you just pretend
| you started working after that update on main.
| fc417fc802 wrote:
| For the reason I stated that you quoted right there.
| Separating the potentially quite large set of changes of
| the initial (properly working) feature from the (hopefully
| not too large) set of changes reconciling that feature with
| the other (apparently incompatible in this example)
| feature. It provides yet another option for filtering the
| irrelevant from the relevant thus could prove quite useful
| at times.
|
| Recall that the entire premise is that there's a bug (the
| allergy). So at some point a while back something went
| wrong and the developer didn't notice. Our goal is to pick
| up the pieces in this not-so-ideal situation.
|
| What's the advantage of "cleaning up" here? Why pretend
| anything? In this context there shouldn't be a noticeable
| downside to having a few extra kilobytes of data hanging
| around. If you feel compelled to "clean up" in this
| scenario I'd argue that's a sign you should be refactoring
| your tools to be more ergonomic.
|
| It might be worthwhile to consider the question, why have
| history in the first place? Why not periodically GC
| anything other than the N most recent commits behind the
| head of each branch and tag?
| javier123454321 wrote:
| Until you commit to trunk, you haven't gotten the dog. You're
| proposing getting a dog. The action of getting the dog happens
| at merge to trunk. That's when history is created.
| embedding-shape wrote:
| > The response is often hesitation or outright fear. I get it.
| Rebase has a reputation for destroying work, and the warnings you
| see online don't help.
|
| The best method for stop being terrified of destructive
| operations in git when I first learned it, was literally "cp -r
| $original-repo $new-test-repo && go-to-town". Don't know what
| will happen when you run `git checkout -- $file` or whatever?
| Copy the entire directory, run the command, look at what happens,
| then decide if you want to run that in your "real" repository.
|
| Sound stupid maybe, but if it works, it works. Been using git for
| something like a decade now, and I'm no longer afraid of
| destructive git operations :)
| psychoslave wrote:
| One step further which is in-scope-of-the-tool spirit will be
| git clone locally your repository.
|
| And still one step further, just create a new branch to deal
| with the rebase/merge.
|
| Yes there are may UX pain points in using git, but it also has
| the great benefits of extremely cheap and fast branching to
| experiment.
| afiori wrote:
| in my experience some of the trickiest situations are around
| gitignore file updates, crlf conversion, case [in]sentivity,
| etc. where clones and branches are less useful as a testing
| ground.
| embedding-shape wrote:
| Yeah, works for normal "lets try out what happens when I do
| this" but it can get messy, depending on what you're trying
| out. That's why I always recommended beginners to literally
| "cp -r" the entire directory instead, together with the git
| repository, so they can feel freer to completely experiment
| and not be afraid of loosing anything.
|
| I guess it's actually more of a mental "divider" than
| anything, it tends to relax people more when they can
| literally see that their old stuff is still there, and I
| think git branches can "scare" people in that way.
|
| Granted, this is about people very new to git, not people who
| understands what is/isn't destructive, and just because a
| file isn't on disk doesn't mean git doesn't know exactly what
| it is.
| freedomben wrote:
| > _Granted, this is about people very new to git, not
| people who understands what is /isn't destructive, and just
| because a file isn't on disk doesn't mean git doesn't know
| exactly what it is._
|
| I've been using git almost exclusively since 2012 and feel
| very comfortable with everything it does and where the
| sharp edges are. Despite that, I still regularly use the cp
| -r method when doing something even remotely risky. The
| reason being, that I don't _want_ to have to spend time
| unwinding git if I mess something up. I have the
| understanding and capability of doing so, but it 's way
| easier to just cp -r and then rm -rf && cp -r again if I
| encounter something unexpected.
|
| Two examples situations where I do this:
|
| 1. If I'm rebasing or merging with commits that have a
| moderate to high risk of merge conflicts that could be
| complicated. I might get 75% through and then hit that one
| commit where there's a dozen spots of merge conflict and it
| isn't straightforwardly clear which one I want (usually
| because I didn't write them). It's usually a lot easier to
| just rm -rf the copy and start over in a clean cp -r after
| looking through the PR details or asking the person who
| wrote the code, etc.
|
| 2. If there are uncommitted files in the repo that I don't
| want to lose. I routinely slap personal helper scripts or
| Makefiles or other things on top of repos to ease my
| workflow, and those don't ever get committed. If they are
| non-trivial then I usually try to keep a copy of them
| somewhere else in case I need to restore, but I'm not alway
| ssuper disciplined about that. The cp -r method helps a lot
|
| There are more scenarios but those are the big two that
| come to mind.
| codesnik wrote:
| whoa. well, if it really works for you. The thing is, git has
| practically zero "destructive" commands, you almost always
| (unless you called garbage collector aggressively) return to
| the previous state of anything committed to it. `git reflog` is
| a good starting point.
|
| I think i've seen someone coded user-friendlier `git undo`
| front for it.
| embedding-shape wrote:
| I expanded on it more here:
| https://news.ycombinator.com/item?id=46601600
|
| TDLR is: people feel safer when they can see that their
| original work is safe, while just making a new branch and
| playing around there _is_ safe in 99% of the cases, people
| are more willing to experiment when you isolate what they
| want to keep.
| bob1029 wrote:
| The fastest way to eliminate fear is to practice. I had the
| team go through it one day. They didn't get a choice. I locked
| us on a screen share until everyone was comfortable with how
| rebasing works. The call lasted maybe 90 minutes. You just have
| to decide one day that you (or the team) will master this shit,
| spend a few hours doing it, and move on.
|
| Rebase is a super power but there are a few ground rules to
| follow that can make it go a lot better. Doing things across
| many smaller commits can make rebase less painful downstream.
| One of the most important things is to learn that sometimes a
| rebase is not really feasible. This isn't a sign that your
| tools are lacking. This is a sign that you've perhaps deviated
| so far that you need to reevaluate your organization of labor.
| thunderbong wrote:
| One of the many things I like about fossil is the 'undo'
| command [0].
|
| Also, since you can choose to keep the fossil repo in a
| separate directory, that's an additional space saver.
|
| [0] https://www3.fossil-scm.org/home/help/undo
| WolfeReader wrote:
| Fossil is great.
| z3dd wrote:
| why copy anything at all? you just need to preserve the head
| and that's it. As simple as `git branch bkp` and that's all.
| recursive wrote:
| In order for that to work you need some level of confidence
| that rebase doesn't mess with your branch. Rebase has a
| reputation for "rewriting history".
| xorcist wrote:
| > cp -r $original-repo $new-test-repo
|
| This is almost exactly what git does, except it's a million
| times faster. Every commit is one of those copies, and you can
| instantly jump to any one of them using git checkout.
|
| If you like this mental model, you'll feel right at home with
| git. You will love git reflog.
| ratchetclank wrote:
| I never understood why rebase is such a staple in the git world.
| For me "loosing" historical data, like on which branch my work
| was done is a real issue.
|
| In the same class, for commit to not have on which branch they
| were created as a metadata is a rel painpoint. It always a mess
| to find what commit were done for what global feature/bugfix in a
| global gitflow process...
|
| I'll probably be looking into adding an commit auto suffix
| message with the current branch in the text, but it will only
| work for me, not any contributors...
| chungy wrote:
| Sounds like you'd be a fan of Fossil (https://fossil-scm.org).
| See for instance: https://fossil-
| scm.org/home/doc/trunk/www/fossil-v-git.wiki#...
| smartmic wrote:
| Let me expand on this with a link to the article "Rebase
| Considered Harmful" [0].
|
| I also prefer Fossil to Git whenever possible, especially for
| small or personal projects.
|
| [0] https://fossil-scm.org/home/doc/trunk/www/rebaseharm.md
| fc417fc802 wrote:
| > Surely a better approach is to record the complete
| ancestry of every check-in but then fix the tool to show a
| "clean" history in those instances where a simplified
| display is desirable and edifying
|
| From your link. The actual issue that people ought to be
| discussing in this comment section imo.
| sigseg1v wrote:
| THIS is the hill I will die on.
|
| Why do we advocate destroying information/data about the
| dev process when in reality we need to solve a UI/display
| issue?
|
| The amount of times in the last 15ish years I've solved
| something by looking back at the history and piecing
| together what happened (eg. refactor from A to B as part
| of a PR, then tweak B to eventually become C before
| getting it merged, but where there are important details
| that only resulted because of B, and you don't realize
| they are important until 2 years later) is high enough
| that I consider it very poor practice to remove the
| intermediate commits that actually track the software
| development process.
| rendaw wrote:
| Isn't this just `--first-parent`? I think that should
| probably be the default in git. Maybe the only way this
| will happen is with a new SCM.
|
| But the git authors are adamant that there's no
| convention for linearity, and somehow extended that to
| why there shouldn't be a "theirs" merge strategy to
| mirror "ours" (writing it out it makes even less sense,
| since "theirs" is what you'd want in a first-parent-
| linear repo, not "ours").
| codesnik wrote:
| it's just "gitflow" is unnecessary complex (for most
| applications). with rebase you can work more or less as with
| "patches" and a single master, like many projects did in 90x,
| just much more comfortably and securely.
| orwin wrote:
| Ideally you only rebase your own commit on your own feature
| branch, just before merging. Having a clean commit history
| before merging make the main branch/trunk more readable.
|
| Also (and especially) it make it way easier to revert a single
| feature if all the relevant commits to that feature are already
| grouped.
|
| For your issue about not knowing which branch the commits are
| from: that why I love merge commits and tree representation (I
| personally use 'tig', but git log also have a tree
| representation and GUI tools always have it too).
| hhjinks wrote:
| Which branch your work was done on is noise, not signal. There
| is absolutely zero signal lost by rebasing, and it prunes a lot
| of noise. _If_ your branch somehow carries information, that
| information should be in your commit message.
| ratchetclank wrote:
| I disagree, without this info, I can't easily tell if any
| commit is part of a feature or is a simple hotfix. I need to
| rely on the commiter to include the info in the commit
| message, which is almost always not the case.
| yxhuvud wrote:
| Nothing stops you from doing both renade and merge commits.
|
| Except perhaps crappy gui options in GitHub. I really wish
| they added that option as a button.
| pluralmonad wrote:
| But you are still relying on them to name the branch in
| such a way it encodes that info. It is unclear why this is
| superior to messages in commits.
| globular-toast wrote:
| It's worse than that: the branch name is lost after a
| merge. That "merge branch xyz" is simply the default
| commit message. So it doesn't matter what you do, commit
| messages are all you have!
| fatbird wrote:
| Every commit message starts with the ticket number of whatever
| issue tracking system you're using. If you're not using issue
| tracking with a system large enough for multiple devs, you've
| got a much bigger problem.
| rich_sasha wrote:
| I have lost ~irretrievably work via rebase.
|
| I was working on a local branch, periodically rebasing it to
| master. All was well, my git history was beautiful etc.
|
| Then down the line I realised something was off. Code that should
| have been there wasn't. In the end I concluded some automatic
| commit application while rebasing gobbled up my branch changes.
| Or frankly, I don't even entirely know what happened (this is my
| best guess), all I know is, suddenly it wasn't there.
|
| No big deal, right? It's VCS. Just go back in time and get a
| snapshot of what the repo looked like 2 weeks ago. Ah. Except
| rebase.
|
| I like a clean linear history as much as the next guy, but in the
| end I concluded that the only real value of a git repo is telling
| the truth and keeping the full history of WTF really happened.
|
| You could say I was holding it wrong, that if you just follow
| this one weird old trick doctor hate, rebase is fine. Maybe. But
| not rebasing and having a few more squiggles in my git history is
| a small price to pay for the peace of mind that my code change
| history is really, really all there.
|
| Nowadays, if something leaves me with a chance that I cannot
| recreate the repo history at any point in time, I don't bother.
| Squash commits and keeping the branch around forever are OK in my
| book, for example. And I always commit with --no-ff. If a commit
| was never on master, it shouldn't show up in it.
| nh2 wrote:
| > Just go back in time and get a snapshot of what the repo
| looked like 2 weeks ago. Ah. Except rebase.
|
| This is false.
|
| Any googling of "git undo rebase" will immediately point out
| that the git reflog stores all rebase history for convenient
| undoing.
|
| Shockingly, got being a VCS has version control for the...
| versions of things you create in it, not matter if via merge or
| rebase or cherry-pick or whatever. You can of course undo all
| of that.
| rich_sasha wrote:
| Up to a point - they are garbage collected, right?
|
| And anyway, I don't want to dig this deep in git internals. I
| just want my true history.
|
| Another way of looking at it is that given real history, you
| can always represent it more cleanly. But without it you can
| never really piece together what happened.
| nh2 wrote:
| The reflog is not a git internal -- it is your local
| repository's "true history", including all operations that
| you ran.
|
| The `git log` history that you push is just that curated
| specific view into what you did that you wish to share with
| others outside of your own local repository.
|
| The reflog is to git what Ctrl+Z is to Microsoft Word.
| Saying you don't want to use the reflog to undo a rebase is
| a bit like saying you don't want to use Ctrl+Z to undo
| mistakes in Word.
|
| (Of course the reflog is a bit more powerful of an undo
| tool than Ctrl+Z, as the reflog is append-only, so undoing
| something doesn't lose you the newer state, you can "undo
| the undo", while in Word, pressing Ctrl+Z and then typing
| something loses the tail of the history you undid.)
|
| Indeed, like for Word, the undo history expires after a
| configurable time. The default is 90 days for reachable
| changes and 30 days for unreachable changes, which is
| usually enough to notice whether one messed up one's
| history and lost work. You can also set it to never expire.
|
| It is fine for people to prefer merge over rebase histories
| to share the history of parallel work (if in turn they can
| live with the many drawbacks of not having linear history).
|
| But it is misleading to suggest that rebase is more likely
| to lose work from interacting with it. Git is /designed/ to
| not lose any of your work on the history -- no matter the
| operation -- via the reflog.
| rich_sasha wrote:
| But it's at best much harder to find stuff in the reflog
| than to simply use git's history browsing tools. "What's
| the state of my never-rebased branch at time X" is a
| trivial question to answer. Undoing a rebase, at best,
| involves some hard resets or juggling commit hashes.
|
| None of it is impossible, but IMHO it's a lot of
| excitement of the wrong kind for essentially no reward.
| seba_dos1 wrote:
| > "What's the state of my never-rebased branch at time X"
| is a trivial question to answer.
|
| Yes, but only because of reflog.
| recursive wrote:
| git log will also do the job, even if you never checked
| out the branch in this workspace.
| OkayPhysicist wrote:
| They're garbage collected after 90 days.
| pabs3 wrote:
| git rebase conflict resolution is a lot less scary with the
| zdiff3 merge.conflictStyle option.
|
| Also incremental rebasing with mergify/git-imerge/git-mergify-
| rebase/etc is really helpful for long-lived branches that aren't
| merged upstream.
|
| https://github.com/brooksdavis/mergify
| https://github.com/mhagger/git-imerge https://github.com/CTSRD-
| CHERI/git-mergify-rebase
| https://gist.github.com/nicowilliams/ea2fa2b445c2db50d2ee650...
|
| I also love git-absorb for automatic fixups of a commit stack.
|
| https://github.com/tummychow/git-absorb
| eddyg wrote:
| _So_ many people don't know about git-absorb! It's fantastic.
| 708145_ wrote:
| I see no need to ever rebase manually, just merge on your branch
| and always fast-forward squash merge (only sane default) with
| GitHub/GitLab/whatever.
| 708145_ wrote:
| _squash merge_ to main ofc.
| DarkNova6 wrote:
| I don't see how this is not the first answer. What tools does
| everybody else work with??
| OkayPhysicist wrote:
| Squash merges are a hacky solution to the git bisect problem
| that was solved correctly by --first-parent 20 years ago. There
| are fully employed software developers working on important
| stuff that literally were never alive in a world where squash
| merges were needed.
|
| Don't erase history. Branch to a feature branch, develop in as
| many commits as you need, then merge to main, always creating a
| merge commit. Oftentimes, those commit messages that you're
| erasing with a squash are the most useful documentation in the
| entire project.
| quacker wrote:
| Using git history as documentation is hacky. A majority of
| feature branch commit messages aren't useful ("fix test case
| X", "fix typo", etc), especially when you are accepting
| external contributions. _IF_ I wanted to use git history as a
| form of documentation (I don 't. I want real documentation
| pages), I'd want the history curated into meaningful commits
| with descriptive commit messages, and squash merging is a
| great way to achieve that. Git bisect is not the only thing I
| do with git history after all.
|
| And if I'm using GitHub/Gitlab, I have pull requests that I
| can look back on which basically retain everything I want
| from a feature branch and more (like peer review discussion,
| links to passing CI tests, etc). Using the Github squash
| merge approach, every commit in the main branch refers back
| to a pull request, which makes this super nice.
| tomaytotomato wrote:
| Github is not Git but I find the Squash and Merge functionality
| on Github's Pull Request system means I no longer need to worry
| about rebasing or squashing my commits locally before rebasing.
|
| At work though it is still encouraged to rebase, and I have
| sometimes forgotten to squash and then had to abort, or just suck
| it up and resolve conflicts from my many local commits.
| cdmckay wrote:
| This
|
| Rebase only makes sense if you making huge PRs where you need
| to break it down into smaller commits to have them make sense.
|
| If you keep your PRs small, squashing it works well enough, and
| is far less work and more consistent in teams.
|
| Expecting your team to carefully group their commits and have
| good commit messages for each is a lot of unnecessary extra
| work.
| ivanjermakov wrote:
| Squash is not Github specific and is part of git:
| git merge --squash
| quacker wrote:
| Right, but they are referring to configuration on a GitHub
| repository that can make squash merge automatic for all pull
| request merges.
|
| e.g. When clicking the big green "Merge pull request" button,
| it will automatically squash and merge the PR branch in.
|
| So then I don't need to remind or wait for contributors to do
| a squash merge before merging in their changes. (Or worse,
| forget to squash merge and then I need to fix up main).
| freeplay wrote:
| Couldn't agree more. Squash merges to main ONLY.
|
| That way, I don't care if your branch contains 100 commits or 1
| commit. I don't need to worry about commit messages like:
|
| - fix 1
|
| - fix 2
|
| - dfljfdlkfdj
|
| - does it work now?
|
| Do whatever you want with your commits on your feature branch.
| Just make sure the title of your PR is clean and follows our
| formatting. Git history is always well formatted and linear.
|
| It's the ideal solution.
| dominicrose wrote:
| When things get messy I use Sublime Merge with two tabs, one with
| the code that's open in VS Code and one with the same project but
| different branch/commit. It works well on Linux. I've managed to
| make it work with Windows + WSL but I don't recommend it.
| flux3125 wrote:
| >the worst case scenario for a rebase gone wrong is that you
| delete your local clone and start over.
|
| Wouldn't it be enough to simply back up the branch (eg, git
| checkout -b current-branch-backup)? Or is there still a way to
| mess up the backup as well?
| aurecchia wrote:
| Yeah, deleting your local clone and starting over should
| normally not be necessary, unless you really mess things up
| badly.
|
| The "local backup branch" is not really needed either because
| you can still reference `origin/your-branch` even after you
| messed up a rebase of `your-branch` locally.
|
| Even if you force-pushed and overwrote `origin/your-branch`
| it's most likely still possible to get back to the original
| state of things using `git reflog`.
| OkayPhysicist wrote:
| For amateurs at Git, recovery branches/tags are probably
| easier to switch back to than digging through reflog.
| Particularly if you're interacting with Git via some GUI that
| hides reflog away as some advanced feature.
| aeinbu wrote:
| > I always use VS Code for this step. Its merge conflict UI is
| the clearest I've found: it shows "Accept Current Change,"
| "Accept Incoming Change," "Accept Both Changes," and "Compare
| Changes" buttons right above each conflict.
|
| I still get confused by vscode's changing the terms used by Git.
| <<Current>> vs <<incoming>> are not clear, and can be understood
| to mean two different things.
|
| - Is "current" what is on the branch I am rebasing on? Or is it
| my code? (It's my code)
|
| - Is "incoming" the code I'm adding to the repo? Or is it what i
| am rebasing on to? (Again, the latter is correct)
|
| I find that many tools are trying to make Git easier to
| understand, but changing the terms is not so helpful. Since
| different tools seldom change to the same words, it just clutters
| any attempts to search for coherent information.
| afiori wrote:
| For merges current is the branch you are on, for rebases it
| helps to see them as a serie of cherry picks, so current would
| be the branch you would be on while doing the cherry pick
| equivalent to this step of the rebase.
| spiffyk wrote:
| Git's "ours"/"theirs" terminology is often confusing to
| newcomers, especially when from a certain (incorrect, but
| fairly common) point of view their meaning may appear to be
| swapped between merge and rebase. I think in an attempt to make
| the terminology less confusing UIs tend to reinvent it, but
| they _always_ fail miserably, ending up with the same problem,
| just with slightly different words.
|
| This constant reinvention makes the situation even worse,
| because now the terminology is not only confusing, but also
| inconsistent across different tools.
| Izkata wrote:
| I think even presenting them as options makes it even more
| confusing to newcomers. Usually I find that neither is
| correct and there's a change on both sides I need to manually
| merge (so I don't even pay attention to the terminology), but
| I've seen co-workers just blindly choose their changes
| because it's familiar looking then get confused when it
| doesn't work right.
| magicalhippo wrote:
| We use SVN at work and it's a nightmare there too, "mine" and
| "theirs" and whatnot. I frequently end up looking at
| historical versions just to verify which is which.
|
| If I have a merge conflict I typically have to be very
| conscious about what was done in both versions, to make sure
| the combination works.
|
| I wish for "working copy" and "from commit 1234 (branch xyz)"
| or something informative, rather than confusing catch-all
| terms.
| WolfeReader wrote:
| Please tell me you are using Git-SVN or Hg-SVN. Using bare
| SVN as a client hasn't been necessary in over a decade.
| magicalhippo wrote:
| Using SmartSVN which makes life a fair bit better but
| still keeps this confusing terminology.
|
| We'll be migrating to Git this year though so.
|
| For reference, the codebase is over 20 years old, and
| includes binary dependencies like libraries. Makes it
| easy to compile old versions when needed, not so easy on
| the repository size...
| xorcist wrote:
| That terminology is identical in git, likely inspired by
| cvs and svn, so that bit probably won't improve.
|
| It's inherently confusing to juggle different trees, and
| clearly you need some terminology for it. At least this
| one has become a bit of a standard.
| magicalhippo wrote:
| Main reason is we have relatively few merge conflicts
| despite merging a lot. So I always forget between
| instances.
| Deadron wrote:
| Just do a normal merge, then squash all your commits in into one,
| using rebase, then a rebase onto a branch is easy.
| game_the0ry wrote:
| I have been contributing code for 10+ years, and I have worked on
| teams that did rebase and others that did not.
|
| Not once have a ever debugged a problem that benefited from
| rebase vs merge. Fundamentally, I do not debug off git history.
| Not once has git history helped debug outside of looking at the
| blame + offending PR and diff.
|
| Can someone tell me when they were fixing a problem and they were
| glad that they rebased? Bc I can't.
| nicoburns wrote:
| The main benefit I've found is when there is work happening
| concurrently in multiple feature branches at once (e.g. by
| different people). Rebase-merging greatly simplifies dealing
| with merge conflicts as you only have a simple diff against a
| single branch to deal with. The more work you have in progress
| at once the more important this becomes.
| skipkey wrote:
| I can give you an example of when I am glad I rebased. There
| have been many times I have been working on a feature that was
| going to take some time to finish. In that case my general
| workflow is to rebase against main every day or two. It lets me
| keep track of changes and handle conflicts early and makes the
| eventual merge much simpler. As for debugging I've never
| personally had to do this, but I imagine git bisect would
| probably work better with rebased, squashed commits.
| hnben wrote:
| > I can give you an example of when I am glad I rebased
|
| I think the question was about situations where you were glad
| to rebase, when you could have merged instead
| alemanek wrote:
| They kind of spoke to it. Rebasing to bring in changes from
| main to a feature branch which is a bit longer running
| keeps all your changes together.
|
| All the commits for your feature get popped on top the
| commits you brought in from main. When you are putting
| together your PR you can more easily squash your commits
| together and fix up your commit history before putting it
| out for review.
|
| It is a preference thing for sure but I fall into the
| atomic, self contained, commits camp and rebase workflows
| make that much cleaner in my opinion. I have worked with
| both on large teams and I like rebase more but each have
| their own tradeoffs
| thousand_nights wrote:
| i don't think i have ever even looked at what order the
| commits are, i only care about the diff vs the target
| branch when reviewing
|
| especially since every developer has a different idea of
| what a commit should be, with there being no clear right
| answer
| rendaw wrote:
| You can bring in changes and address conflicts early with
| merge too, I believe that's GP's point.
| alemanek wrote:
| Yes but specifically with a rebase merge the commits
| aren't interleaved with the commits brought in from
| mainline like they are with a merge commit.
|
| EDIT: I may have read more into GPs post but on teams
| that I have been on that used merge commits we did this
| flow as well where we merged from main before a PR.
| Resolving conflicts in the feature branch. So that
| workflow isn't unique to using rebase.
|
| But using rebase to do this lets you later more easily
| rewrite history to cleanup the commits for the feature
| development.
| cryptonector wrote:
| That's hard to answer because I only rebase.
| bluGill wrote:
| I used hg (mercurial) before git. Every time I see someone
| make an argument like yours I think "only because git's
| merge/branch model is bad and so you need hacks to make it
| acceptable".
|
| Git won, which is why I've been using it for more than 10
| years, but that doesn't mean it was ever best, it was just
| most popular and so the rest of the eco system makes it worth
| it accepting the flaws (code review tools and CI system both
| have much better git support - these are two critical things
| that if you use anything else will work against you).
| doctorpangloss wrote:
| Not only is git not the best, but one of the central value
| props of coding agents and chatbots used for programming is
| not having to use git in order to interact with free code.
| BeetleB wrote:
| I do the same except with merge. I don't see how rebase makes
| it any better.
| samuelson wrote:
| It avoids adding merge commits to your history.
| BeetleB wrote:
| I see no reason to avoid that.
| d_watt wrote:
| Once we had a slowdown in our application that went unadressed
| for a couple of months. Using git bisect to binary search
| across a bunch of different commits and run a perf test, every
| commit being a "good" historical commit allowed that to be much
| easier, and I found the offending commit fast.
| game_the0ry wrote:
| Ok, I see. This is a use case I did not think about. Worthy
| of a blog post, I think.
|
| Besides testing for a perf slow down, any other use cases for
| git bisect + rebase?
| OptionOfT wrote:
| In fact, for searching how a file got to the state it is I
| prefer that when PRs are merged, they are merged and not
| rebased. I want the commit shas to be the same.
|
| Rebasing on main loses provenance.
|
| If you want a clean history doing it in the PR, before merging
| it. That way the PR is the single unit of work.
| game_the0ry wrote:
| > That way the PR is the single unit of work.
|
| Well if I have a diff of the PR with just the changes, then
| the PR is already a "unit of work," regardless of merge or
| rebase, right?
| yawaramin wrote:
| Merging a PR with rebase doesn't lose provenance. You can
| just keep all the commits in the PR branch. But even if you
| squash the branch into a single commit and merge (which these
| tools automate and many people do), it still doesn't lose
| provenance. The provenance is the PR itself. The PR is
| connected to a work item in the ticketing system. The git
| history preserves all the relevant info.
| noisem4ker wrote:
| The provenance that is lost is the original base.
| yawaramin wrote:
| No, the original base is in the commit history. It's just
| not relevant any more after rebase. It's like your
| individual keystrokes before a commit are not relevant
| any more after a commit. They're not lost provenance.
| dcre wrote:
| This is the post that made jj click for me, and not
| coincidentally it is about a rebase operation that feels
| complicated in git but trivial in jj.
|
| https://lottia.net/notes/0013-git-jujutsu-miniature.html
| any1 wrote:
| > Fundamentally, I do not debug off git history.
|
| Are you saying that you've never used git bisect? If that's the
| case, I think you're missing out.
| yawaramin wrote:
| From what I can tell the vast majority of developers don't
| use git bisect and never will.
| appplication wrote:
| FWIW, having squashed merge commits also reduces the
| relevance of bisect. It can still be useful but it's not
| necessarily as critical of a tool.
| cryptonector wrote:
| This. This is why small commits are nice. If you do that
| you might as well rebase. If you squash you lose.
| PaulDavisThe1st wrote:
| Git bisect is a wonder, especially combined with its ability
| to potentially do the success/fail testing on its own (with
| the help of some command you provide).
|
| It is a tragedy that more people don't know about it.
| zbentley wrote:
| Bisect is one of those things where if you're on a certain
| kind of project, it's _really_ useful, and if you 're not on
| that kind of project you never need it.
|
| If the contributor count is high enough (or you're otherwise
| in a role for which "contribution" is primarily adjusting
| others' code), or the behaviors that get reported in bugs are
| specific and testable, then bisect is invaluable.
|
| If you're in a project where buggy behavior wasn't
| _introduced_ so much as _grew_ (e.g. the behavior evolved A -
| > B -> C -> D -> E over time and a bug is reported due to
| undesirable interactions between released/valuable features
| in A, C, and E), then bisecting to find "when did this start"
| won't tell you that much useful. If you often have to write
| bespoke test scripts to run in bisect (e.g. because "test for
| presence of bug" is a process that involves
| restarting/orchestrating lots of services and/or debugging by
| interacting with a GUI), then you have to balance the time
| spent writing those with the time it'd take for you to figure
| out the causal commit by hand. If you're in a project where
| you're personally familiar with roughly what was released
| when, or where the release process/community is well-
| connected, it's often better to promote practices like "ask
| in Slack/the mailing list whether anyone has made changes to
| ___ recently, whoever pipes up will help you debug" rather
| than "everyone should be really good at bisect". Those aren't
| mutually exclusive, but they both do take work to install in
| a community and thus have an opportunity cost.
|
| This and many other perennial discussions about Git
| (including TFA) have a common cause: people assume that
| criticisms/recommendations for how to use Git _as a release
| coordinator /member of a disconnected team of volunteers_
| apply to people who use Git who are _members of small,
| tightly-coupled teams of collaborators_ (e.g. working on
| closed-source software).
| nothrabannosir wrote:
| Debugging from git history is a separate question from merge vs
| rebase. Debugging from history can be done with non-rebased
| merges, with rebased merges, and with squashed commits, without
| any noticeable difference. Pass `--first-parent` to git-log and
| git-bisect in the first two cases and it's virtually identical.
|
| My preference for rebasing comes from delivering stacked PRs:
| when you're working on a chain of individually reviewable
| changes, every commit is a clean, atomic, deliverable patch.
| git-format-patch works well with this model. GitHub is a pain
| to use this way but you can do it with some extra scripts and
| setting a custom "base" branch.
|
| The reason in that scenario to prefer rebasing over "merging in
| master" is that every merge from master into the head of your
| stack is a stake in the ground: you can't push changes to
| parent commits anymore. But the whole point of stacked diffs is
| that I want to be able to identify different issues while I
| work, which belong to different changes. I want to clean things
| up as I go, without bothering reviewers with irrelevant
| changes. "Oh this README could use a rewrite; let me fix that
| and push it all the way up the chain into its own little
| commit," or "Actually now that I'm here, let me update
| dependencies and ensure we're on latest before I apply my
| changes". IME, an ideal PR is 90% refactors and "prefactors"
| which don't change semantics, all the way up to "implemented
| functionality behind a feature flag", and 10% actual changes
| which change the semantics. Having an editable history that you
| can "keep bringing with you" is indispensible.
|
| Debugging history isn't really related. Other than that this
| workflow allows you to create a history of very small, easily
| testable, easily reviewable, easily revertible commits, which
| makes debugging easier. But that's a downstream effect.
| game_the0ry wrote:
| > Debugging from git history is a separate question from
| merge vs rebase.
|
| But the main benefit proponents or rebase say its for keeping
| the history clean which also makes it easier to pinpoint and
| offending commit.
|
| Personally, a clean commit history was never something that
| made my job easier.
|
| > Other than that this workflow allows you to create a
| history of very small, easily testable, easily reviewable,
| easily revertible commits, which makes debugging easier. But
| that's a downstream effect.
|
| I would agree that it is important for commits to go from
| working state to working state as you are working on a task,
| but this is an argument for atomic commits, not about commit
| history.
| macintux wrote:
| > Personally, a clean commit history was never something
| that made my job easier.
|
| How do you define "clean"? I've certainly been aided by
| commit messages that help me identify likely places to
| investigate further, and hindered by commit messages that
| lack utility.
| Jare wrote:
| > How do you define "clean"?
|
| In the context of merge vs rebase, I think "clean" means
| linear, without visible parallel lines. Quality of commit
| messages is orthogonal. I agree with the poster that this
| particular flavor of "clean" (linear) has never ever
| helped me one bit.
| convolvatron wrote:
| we're in the minority I think. I always find it easier to
| just debug a problem from first principles instead of
| assuming that it worked at some point and then someone
| broke it. often times that assumption is wrong, and often
| times the search for bad commit is more lengthy and less
| informative than doing the normal experimental process. I
| certainly admit that there are ases where the test is
| easily reproducible and bisect just spits out the answer,
| but that a seductive win. I certainly wouldn't start by
| reading the commit log and rewinding history until I at
| least had a general idea of the source of the problem, and
| it wasn't immediately obvious what to try next to get more
| information.
|
| if you look at it as in investment in understanding the
| code base more than just closing the ticket as soon as
| possible, then the 'lets see what really going on here'
| approach makes more sense.
| Jare wrote:
| > I certainly wouldn't start by reading the commit log
|
| Me neither, for what is worth. But even if the idea is
| "when in order to figure out this issue, you have to go
| to the history", a linear history and a linear log never
| helped me either. For example, to find where a certain
| change happened to try to understand what was the intent,
| what I need is the commit and its neighbors, which works
| just as well with linear vs branching history because the
| neighbors are going to still be nearby up and down, not
| found via visual search.
| __MatrixMan__ wrote:
| If you haven't used git bisect to find a regression, you should
| try it.
|
| You can write a test (outside of source control) and run `git
| bisect good` on a good commit and `git bisect bad` on bad one
| and it'll do a binary search (it's up to you to rerun your test
| each time and tell git whether that's a good or a bad commit).
| Rather quickly, it'll point you to the commit that caused the
| regression.
|
| If you rebase, that commit will be part of a block of commits
| all from the same author, all correlated with the same feature
| (and likely in the same PR). Now you know who you need to talk
| to about it. If you merge, you can still start with the author
| of the commit that git bisect found, but it's more likely to be
| interleaved with nearby commits in such a way that when it was
| under development, it had a different predecessor. That's a
| recipe for bugs that get found later than they otherwise
| would've.
|
| If you're not using git history to debug, you're probably not
| really aware of which problems would've turned out differently
| if the history was handled differently. If you do, you'll catch
| cases where one author or another would've caught the bug
| before merging to main, had they bothered to rebase, but
| instead the bug was only visible after both authors thought
| they were done.
| PaulDavisThe1st wrote:
| > it's up to you to rerun your test each time and tell git
| whether that's a good or a bad commit
|
| not true. You can use git bisect run script-
| command arguments
|
| where script-command is a ... script that will test the
| result of the build.
| simonw wrote:
| Do you ever use git bisect?
|
| I like to keep a linear history mainly so I don't have to think
| very hard about tools like that.
| tcoff91 wrote:
| --first-parent with bisect really helps when the history is
| messy.
| recursive wrote:
| I've used git bisect on a repo whose commit graph is at least
| 20-wide at some points. In the two cases I used it, it
| identified the individual commit. I didn't think very hard
| about it. It was the first time I used bisect. Maybe I got
| lucky.
| tsimionescu wrote:
| I have often been happy to have a clean linear history when
| asking myself things like "does build X.Y.Z include this buggy
| change I found in commit abcdefg?". With a history full of
| merges, where a commit from 1st of January might be merged only
| on the 20th of July, this gets MUCH harder to answer.
|
| This is especially true if you have multiple repos and builds
| from each one, such that you can't just checkout the commit for
| build X.Y.Z and easily check if the code contains that or not
| (you'd have to track through dependency builds, checkout those
| other dependencies, possibly repeat for multiple levels). If
| the date of a commit always reflects the date it made it into
| the common branch, a quick git log can tell you the basic info
| a lot of the time.
| languid-photic wrote:
| I manage a maintained fork and periodically rebase our changes
| on top of upstream.
|
| In this case, rebasing is nice because our changes stay in a
| contiguous block at the top (vs merging which would interleave
| them), so it's easy for me and others to see exactly where our
| fork diverges.
| friedbeef wrote:
| Doesn't that mean you have to fix all the merge conflicts
| introduced by your commits on every rebase though?
| skribanto wrote:
| rerere can help, but OP probably has their own workflow
| chuckadams wrote:
| Git has gotten pretty smart about that recently: once you
| resolve a conflict, if you get the same conflict again it
| automatically resolves it the same way. Works for both
| rebase and merge.
| froh wrote:
| if you don't have a merge from main into the branch further
| down, then git only bothers you about the most recently
| introduced conflicts conflicts --- the ones you'd have to
| resolve anyhow, and it remembers how you've resolved those.
| cryptonector wrote:
| You'd have merge conflicts whether you merge or rebase.
| gwking wrote:
| This may be outdated because git's defaults have improved a lot
| over the years. When I first used git on a team was in 2011. As
| I recall, there were various commands like git log -p that
| would show nothing for a merge commit. So without extra
| knowledge of the git flags you would not find what you were
| looking for if it was in a side path of the merge history. This
| caused a lot of confusion at times. We switched to a rebase
| approach because linear history is easier for people to use.
|
| To answer your question directly, if somewhat glibly, I'm glad
| I rebased every time I go looking for something in the history
| because I don't have to think about the history as a graph.
| It's easier.
|
| More to your point, there are times when blame on a line does
| not show the culprit. If you move code, or do anything else to
| that line, then you have to keep searching. Sometimes it's
| easier to look at the entire patch history of a file. If there
| is a way to repeatedly/recursively blame on a line, that's cool
| and I'd love to know about it.
|
| I now manage two junior engineers and I insist that they squash
| and rebase their work. I've seen what happens if they don't.
| The merges get tangled and crazy, they include stuff from other
| branches they didn't mean to, etc. the squash/rebase flow has
| been a way to make them responsible for what they put into the
| history, in a way that is simple enough that they got up to
| speed and own it.
| rpcope1 wrote:
| I have worked on several codebases where it was enforced that
| the commit be rebased off of whatever the main branch was, all
| units of work squashed to a single commit, and only "working"
| code be checked into the main branch. This gives you a really
| good linear history, and when you're disciplined about writing
| good final commit messages and tagging them to a ticket, it
| means bisecting to find challenging bugs later becomes
| tractable, as each commit nominally should work and should be
| ready to deploy for testing. I've personally solved a number of
| challenging regressions this way.
| drysine wrote:
| >each commit nominally should work
|
| Except it can be the result of 10 squashed commits.
| bastardoperator wrote:
| Which is the entire point of it. Why should I look at ten
| commits when I can look at one and get the same exact data?
| Why should I pollute my production history for what a is
| likely a bunch of debugging commits? The branch is a
| scratchpad, you should feel empowered within your own
| branch, rebase allows you to be lazy in the development
| cycle while presenting a nice clean set of changes at the
| end of it.
| bonzini wrote:
| You can split your work in multiple commits and at the
| same time drop/squash debugging or wip changes. The
| result allows you to go into much better detail than a PR
| description.
| shawndumas wrote:
| Yes! When you are deep in the code, your brain operates
| in a non-linear way. You try a solution, it breaks a
| test. You patch the test. You realize the variable name
| is wrong. You fix a typo.
|
| Without Squash, the main branch history becomes a
| timeline of your mental struggle.
|
| With Squash, the main branch becomes a catalog of
| features delivered.
|
| No body needs to take a trip on the struggle bus with
| me...
| Yeroc wrote:
| Most of those 10 squashed commits likely had commit
| comments like: "Cleanup based on PR feedback." etc.
| drysine wrote:
| That's what --amend and --fixup are for.
| cryptonector wrote:
| I think one should be allowed to push commits that don't
| build or pass tests provided a) they are marked as such (so
| you can skip them sooner when bisecting) and b) the HEAD
| commit after each push does build and pass tests.
| jefurii wrote:
| I use `git rebase` all the time, along with `git add -p`, `git
| diff` and other tools. It helps me to maintain logical commit
| history.
|
| - Reshuffle commits into a more logical order. - Edit commit
| subjects if I notice a mistake. - Squash (merge) commits.
| Often, for whatever reason pieces of a fix end up in separate
| commits and it's useful to collect and merge them.
|
| I'd like to make every commit perfect the first time but I
| haven't managed to do that yet. git-rebase really helps me
| clean things up before pushing or merging a branch.
| e40 wrote:
| This "debate" is just insane.
|
| Any workflow that has a review process uses rebase. FULL STOP.
|
| If you don't have your code reviewed and you push code to a
| shared repo, fine, don't use rebase if you don't want to.
| xorcist wrote:
| What is the argument here? Does it still hold if you
| s/rebase/comments/g ?
|
| Of course a readable code history aids in debugging. Just as
| comments and indentation do. None of these are technically
| necessary, but still a good idea.
|
| Of course running the rebase command doesn't guarantee a
| readable commit history, but it's hard to craft commits without
| it. Each and every commit on linux-kernel has been rebased
| probably a dozen times.
| douglee650 wrote:
| Isn't it more of a style decision where if your team rebases,
| and practices clean code discipline, and excellence is a habit
| rather than an enforcement -- the signals visibly emit in
| `status`.
|
| Most committers don't really understand remotes, much less
| rebasing.
| mrkeen wrote:
| Any time I'm doing anything remotely to do with merging, I use
| 'git diff' or 'git difftool'.
|
| If I diff against master, I see changes in 300+ files, when
| I've only changed 5 (because other people have changed 300+
| files.)
|
| > Fundamentally, I do not debug off git history.
|
| Neither. The usual argument I hear against rebase is that it
| destroys history. Since I don't debug off git history, I'm
| quite happy to destroy it, and get back to diffing my 5-file
| changes against (current) master.
| MrDarcy wrote:
| Two very useful use cases for rebase: 1) rewrite history to
| organize the change list clearly. 2) stacked pull requests of
| arbitrary depth.
|
| You've never run a bisect to identify which commit introduced a
| specific behavior?
|
| This is when I've found it most useful. Having commits merged
| instead of squashed narrows down and highlights the root
| problem.
|
| It's a rare enough situation I don't push for merge commits
| over squashed rebases because it's not worth it, but when I
| have had to bisect and the commits are merged instead of
| squashed it is very very useful.
|
| Those commit authors are who I noted as clear thinkers and have
| tracked over my career to great benefit.
| cryptonector wrote:
| Whenever I go spelunking in the history I always find clean,
| linear history, with small commits (where possible) to be much
| easier to understand and search than merges.
| mathis-l wrote:
| I've worked on a code base that was about 15 years old and had
| gone through many team changes. It was a tricky domain with
| lots of complicated business logic. When making changes to the
| code, the commit history was often the only way to figure out
| if certain behavior was intended and why it was implemented
| this way. Documentation about how the product should behave
| often lacked the level of detail. I was certainly always
| thankful when a dev that was long gone from the team had
| written commit messages that communicated the intent behind a
| change.
| MeteorMarc wrote:
| Nice, git rerere would have saved me in the past.
| Myrmornis wrote:
| > the worst case scenario for a rebase gone wrong is that you
| delete your local clone and start over. That's it. Your remote
| fork still exists.
|
| This is absolute nonsense. You commit your work, and make a
| "backup" branch pointing at the same commit as your branch. The
| worst case is you reset back to your backup.
| dcre wrote:
| In about 12 years of using git (jj user now) I almost never
| rebased through the CLI, but I found shuffling branches around in
| a GUI pretty intuitive. I liked GitUp[0], which gave me undo way
| before jj existed.
|
| The common view that a Git GUI is a crutch is very wrong, even
| pernicious. To me it is the CLI that is a disruptive mediation,
| whereas in a GUI you can see and manipulate the DAG directly.
|
| Obligatory jj plug: before jj, I would have agreed with the top
| comment[1] that rebasing was mostly unnecessary, even though I
| was doing it in GitUp pretty frequently -- I didn't think of it
| as rebasing because it was so natural. Now that I use jj I see
| that the cost-benefit analysis around git rebase is dominated by
| the fact that both rebasing and conflict resolution in git are a
| pain in the ass, which means the benefit has to be very high to
| compensate. In jj they cost much less, so the neatness benefit
| can be quite small and still be worth it. Add on the fact that
| Claude Code can handle it all for you and the cost is down to
| zero.
|
| [0]: https://gitup.co/
|
| [1]: https://news.ycombinator.com/item?id=46602056
| jonfw wrote:
| Coding agents are excellent at solving merge and rebase conflicts
| according to natural language instruction.
| 6LLvveMx2koXfwn wrote:
| was fully expecting: mv folder folder-old
| git clone git@github/folder
| phrotoma wrote:
| git rebase appears to be a random number generator to me. I've
| got two PRs in flight, I realize that one branch requires
| something I did in the other branch. I go merge branch one, then
| rebase branch two off main. Half the time; success, get on with
| my day. The other half of the time; anarchy, madness, dogs and
| cats living together.
|
| I remain terrified.
| skeptrune wrote:
| i hope ai agents read this
| jimbobimbo wrote:
| Rebase is easy and not terrifying. Here's a 1k word article on
| how to do it correctly.
|
| Or just do a merge and move on with your life.
| bheadmaster wrote:
| If you want to have a linear history on main, either always
| rebase your branch onto main, or merge but only accept squashed
| commits onto main.
| WolfeReader wrote:
| I would prefer to have accurate history over linear
| "history".
| mathisfun123 wrote:
| > Here's a 1k word article
|
| lol if 1k words is "not easy" for you, i think you have bigger
| problems than merge vs rebase.
| darknavi wrote:
| It's funny because I learned git on the job and we exclusively
| used rebase when I was learning my git fundamentals. I wouldn't
| say merging scares be, but it's never a tool a reach for.
| DHRicoF wrote:
| I don't understand why I would push to origin my local branch.
| This will (potentially) require multiple push -f. I prefer to
| share the work in a state I considere complete.
|
| As an alternative, just create a new branch! `git branch
| savepoint-pre-rebase`. That's all. This is extremely cheap (just
| copy a reference to a commit) and you are free to play all you
| want.
|
| You are a little more paranoid? `git switch -c test-rebase` and
| work over the new branch.
| throwaway7783 wrote:
| I avoid rebase like plague (perhaps because of my early
| experiences with it). I used to get continuous conflicts for the
| same commits again and again, and the store and replay kinda
| helped with it but not always. Merge always worked for me (once I
| resolve conflicts, thats the end of it). Now I always merge main
| into my feature branch and then merge it back to main when ready.
| Does it pollute the history? Maybe, but Ive never looked. It does
| not matter to our team.
| literallyroy wrote:
| I think the callout to squash first will be helpful (if your
| lots of commits aren't good info themselves)
| throwaway7783 wrote:
| Perhaps. But you can see the DX of rebase is abysmal compared
| to merge. squash, rerere, force push, remember to push to
| remote before rebase, more coordination if multiple people
| are working on feature branch etc.
|
| I still prefer merge. Its simple and gets out of my way as
| long as I dont care about purity of history
| sesuximo wrote:
| TIL ppl are afraid of rebase lmao
| quacker wrote:
| _Rebasing replays your commits on top of the current main branch,
| as if you'd just created your branch today. The result is a
| clean, linear history that's easier to review and bisect when
| tracking down bugs._
|
| The article discusses why contributors should rebase their
| feature branches (pull request).
|
| The reason they give is for clean git history on main.
|
| The more important reason is ensure the PR branch actually works
| if merged into current main. If I add my change onto main, does
| it then build, pass all tests, etc? What if my PR branch is old,
| and new commits have been added onto main that I don't have in my
| PR branch? Then I can merge and break main. That's why you need
| to update your PR branch to include the newer commits from main
| (and the "update" could be a rebase or a merge from main or
| possibly something else).
|
| The downside of requiring contributors to rebase their PR branch
| is (1) people are confused about rebase and (2) if your
| repository has many contributors and frequent merges into main,
| then contributors will need to frequently rebase their PR branch,
| and each rebase their PR checks need to re-run, which can be time
| consuming.
|
| My preference with Github is to squash merge into main[1] to keep
| clean git history on main. And to use merge queue[2], which
| effectively creates a temp branch of main+PR, runs your CI
| checks, and then the PR merge succeeds into main only if checks
| pass on the temp branch. This approach keeps super clean history
| on main, where every commit includes a specific PR number, and
| more importantly minimizes friction for contributors by reducing
| frequent PR rebases on large/busy repos. And it ensures main is
| never broken (as far as your CI checks can catch issues). There's
| also basically no downside for very small repos either.
|
| 1. https://docs.github.com/en/repositories/configuring-
| branches...
|
| 2. https://docs.github.com/en/repositories/configuring-
| branches...
| g0xA52A2A wrote:
| > Before rebasing, push your current work to your remote fork.
| This gives you a backup you can recover from if anything goes
| wrong
|
| I don't follow this. Just abort the rebase?
| globular-toast wrote:
| > Rebase has a reputation for destroying work, and the warnings
| you see online don't help.
|
| Everyone using git needs to accept the following. Say it out
| aloud if you have to: no command in git can ever modify or delete
| a commit.
|
| After a botched rebase your old work is one simple reset away
| using the reflog. Then you can have another go or reach out for
| help.
| aib wrote:
| My default pull is ff-only. I don't like merging _or_ rebasing by
| default.
|
| When working in a short-lived branch, I like to rebase. I usually
| get no or simply easy-to-solve conflicts. I like my small and
| numerous commits stacked on top of the current develop.
| Regardless or whether we squash or not.
|
| For long-lived branches (and technically for hard merges, though
| I've been using rerere more and more) merge is a better option.
|
| What kills bisect, IMO, is large commits or commits with multiple
| subjects/goals. That's the reason I don't like squashed PRs.
| jdthedisciple wrote:
| Why would you rebase onto master locally in a team environment?
|
| The way to do this are pull requests on the _remote_.
| parasti wrote:
| Been using git since 2008, and this looks more intimidating than
| helpful. git rebase takes a list of patches and applies them one
| by one on top of a given "base" commit. And that's it. It's not
| all this complicated git command soup. It's just patches. No
| objects, no sha1s, no metadata, no branches, just literal textual
| diffs applied in order. It's the dumbest and also one of the most
| powerful things about git if you care at all about a readable
| history. If you don't, that's fine, but in some circles, e.g.
| most (if not all) open source projects, patch management and
| history hygiene is a very important part of good collaboration.
| kwar13 wrote:
| That was great. I have run into this issue and had a lot of
| difficulty rebasing my changes.
| racl101 wrote:
| One thing I still love about blogs like this that AI can never
| replace is that it takes a topic that might seem complicated to
| some people such as myself (Git Rebase does actually terrify me)
| and it talks about it in great detail in a way where I don't have
| to know what to ask. I don't have to prompt about something I
| don't even know where to begin. The topic is introduced and
| elaborated on while speaking to a general audience. So that's why
| I still like to see tech blogs out there.
| Groxx wrote:
| I also get tons of mileage out of This One Weird Trick: make a
| new branch first. Every single time it's non-trivial, just abort
| and branch before continuing.
|
| Then if you screw up, even several steps later when it's hard to
| un-rebase a portion, _you just go back to the original_. No need
| to dig through the ever-confusing reflog format, just use
| branches.
|
| Once you're fully happy with it, you can push that new one, or
| just go back to your original and `git reset --hard after-rebase-
| branch` to adopt the new history.
| tigerlily wrote:
| I do this, and with TortoiseGit I just pick and choose the good
| bits and put them as atomic changes in their own branches and
| PRs.
___________________________________________________________________
(page generated 2026-01-13 23:00 UTC)