Live data from Hacker News

Git rebase, what can go wrong

jvns.ca

331–340 of 404 posts

Re: Git rebase, what can go wrong

#331
post #160
post #128

Earlier quoted context omitted.

Because unless it's the most trivial of features, you'll break it up into smaller commits which each explain what they are doing and make reviewing the change easier. As a simple example, I recently needed to update a json document that was a list of objects. I needed to add a new key/value to each object. The document had been hand edited over the years and had never been auto-formatted. My PR ended up being three c…

In general I agree with you, there are absolutely times where you want to retain commit history on a particular branch (although I try to keep the source tree from knowing about things like commit IDs). I would argue that those are by far the minority of PRs that I see. As I mentioned in another comment, _most_ PRs that I see have a ton of intermediary commits that are only useful for that branch/PR/review process (f…

> only useful for that branch/PR/review process (fixing tests, whitespace, etc).

I have had bugfix cases where, digging through the repo history, both of those examples accidentally introduced the bug (the first because the person who made the original change didn't completely understand a business rule so it changed both the code and the test, the second because of a typo in python that only affected a small subset of the data). Keeping the commit separate let me see very quickly what happened and what the intent actually was.

Re: Git rebase, what can go wrong

#332

Earlier quoted context omitted.

> As soon as you do a rebase, you're rewriting history. Agreed. But the rewrite occurs in your private branch. It's history is just as private as the undo list in your editor. No one cares about what's going on in your editors undo list. And by the same logic they shouldn't care about commits in a private branch. > You're losing information about points of time and specific states that actually existed If you avoid r…

> Agreed. But the rewrite occurs in your private branch. It's history is just as private as the undo list in your editor. No one cares about what's going on in your editors undo list. And by the same logic they shouldn't care about commits in a private branch. The rebase becomes part of the public branch eventually, inflicting your lies on everyone else. > If you avoid rebase, then you end up "rebasing" without rebas…

I think the crux of the argument is what you think about private git commits. You may think of them as "holy" history. Assuming the commits are still private, I give them no more prestige than the editor's undo log.

What do you think of the editors undo log? It's a very real historical log. Should it be treated as "holy" history too? If not, what makes the undo log less true/important than a private git commit log?

Re: Git rebase, what can go wrong

#333
post #201

Earlier quoted context omitted.

> why spend time on a ‘nice’ commit history in a (smallish) feature branch when you can squash merge later. Several reasons: * facilitates much better code review discussions * enables use of git bisect to locate bugs * allows for informative commit messages associated with the changes * communicates clearly to future self about why changes were made

> * enables use of git bisect to locate bugs This is really only viable if each intermediate commit on a development branch is intended to be bug free. If that's the standard you and your team work with, that's fine, but it's not usually my standard; in a development branch, I may commit things that don't even compile, let alone work, if it's a good point to commit.

Of course I commit a lot of garbage commits that don't work, it's super useful to do so. Those never get pushed out into branches that I share to others though - why would I waste their time having them look at those?

What I push out are atomic commits that make sense logically, not an external undo log of my text editor; squashing those on merge provides no benefit and only loses useful information. Squashing should happen before push, not on merge, and there's no reason to have buggy "intermediate" commits recorded in your central remote branch at all.

Re: Git rebase, what can go wrong

#334

Earlier quoted context omitted.

Imagine a feature branch where someone has been keeping it up to date by merging main into it regularly. Now the feature is ready to go into main. You can easily `git merge --squash` that branch into main. You can likely do the same thing manually (as you point out) by running `git rebase -i` if you squash all the commits in the branch. But you’ll never manage to do a genuine rebase, where every commit in the branch…

FWIW I consider `git rebase -i` to be a "genuine rebase"

I do too, except in cases where it’s being used simply as a more complicated UI for `git merge --squash` and there’s no actual “generate a diff and apply it to a different base commit” going on.

Re: Git rebase, what can go wrong

#335

Earlier quoted context omitted.

> keeping a clean history This being a principal reason for VCS, I very much understand the motivation.

"Clean history" is not a principal reason for VCS. "Full history so you don't accidentally lose something and can revert to any point" is the principal reason. When "clean history" conflicts with "full history", the choice should always defer to the latter. Rebase clearly breaks the full history principle.

The principal reason for VCS has nothing to do with "history" at all. It has all to do with "versions".

What exactly the word "version" means depends on context. If you put your essay under git, you probably want to track how it was changing with time. When you hack on some codebase and throw things at wall to see what sticks, you want to be able to go back to the previous attempt should your next one turn out to be useless. You may even want to commit things just because it's a convenient way to send things to be built by CI - so you basically produce "versions" to test.

But when you collaborate with others to develop a project, nobody cares about whether you made typos during your hacking session and had to come back to fix them. It's not a useful information and it never becomes a "version" of a shared project, because why would it? It's just confusing and wastes people's time on review, and makes things like blame and bisect harder to use.

Or when you put a tutorial under a git repo, with each commit representing the next step to achieve a certain outcome. You may have tweaked each step gazillion of times to perfect it, but that "history" is completely irrelevant for the resulting repo. It's meant to store "versions", not "history". Those may correlate, but don't have to.

A git repo is a data structure that you operate on. Treat it as such and use to achieve your goals.

What's funny is that "squash on merge" strategy gets you worst of both worlds. You don't get nicely curated versions in your project because if someone actually cared to fine-tune their MR you just throw that information away, and the rest doesn't care in the first place anyway. Rebasing and squashing is an incredibly useful tool for everyday use by developers in their work, but it often gets used as a band-aid for lazy developers instead.

Re: Git rebase, what can go wrong

#336

Earlier quoted context omitted.

> What matters is that you end up with working systems. That a lot of change happened is just, well, what happened. It doesn't need to be prettied up and made to look like your development occurred in a clockwork march of cleanliness. It literally does not matter unless you spend a lot of time doing git-bisect. And git blame. And git checkout to a past state. It "doesn't matter" only if ease of understanding your pro…

I never use rebase, and I've never once had trouble understanding who did what where and when, even in a large project with 500+ users. That being said, after reading this stuff, I may start using it on my local branches to clean up multiple commits into one tidy one, but that's about it.

> I never use rebase, and I've never once had trouble understanding who did what where and when

And a well-organized commit can also tell you the “why.”

Re: Git rebase, what can go wrong

#337

Earlier quoted context omitted.

FWIW I consider `git rebase -i` to be a "genuine rebase"

I do too, except in cases where it’s being used simply as a more complicated UI for `git merge --squash` and there’s no actual “generate a diff and apply it to a different base commit” going on.

I think we have a rose by any other name situation.

I call that a rebase.

Re: Git rebase, what can go wrong

#338

Earlier quoted context omitted.

Not my experience, nor my team's experience over almost 10 years of using this approach.

I’m firmly in your camp on this one, but I’ve noticed that advocating a tidy history gets a lot of push-back online. I think there is an element of self-fulfilling prophecy here. If a team habitually leaves a messy history behind, that history is rarely going to be useful, so naturally the team has low expectations and sees little value in doing anything to curate it. And if a team isn’t used to making an effort to c…

> I think there is an element of self-fulfilling prophecy here.

This too, but there's another thing at play as well: many developers don't know git at all. They just memorized enough commands to let them do their work. They don't understand what they're doing, so they can't reap the benefits of the tool they use. You won't get much use of RAW photos if all you can do in a graphics editor is clicking "auto enhance" button.

Re: Git rebase, what can go wrong

#339
post #42

Earlier quoted context omitted.

What I think I see these days is squash merges being used lazily to avoid having to do anything to build a clean history with clearly semantically delineated commits. Squash merges are good compared to an alternative where people check in super messy noisy branches, but they unfortunately have a big downside because squash merges can make bisecting and history spelunking more difficult, when the branches that are squ…

> they unfortunately have a big downside because squash merges can make bisecting and history spelunking more difficult, when the branches that are squash merged were big can you help me understand this? It is the exact opposite of my experience. The flow I see is: bug reported, write a git bisect test, identify the feature that introduced it, reach out to that developer/team. This is allowed by squash merges. When I…

I maybe don’t know what you mean about “clean histories”. Speaking for myself, I always expect a history that’s called “clean” to compile error-free at every commit, unless otherwise noted; one of my personal criteria for calling history ‘clean’ is that efforts are made to keep the main branch up and running for every commit.

> how big are your merges? […] Large PRs are an anti-pattern.

Depends, but they sometimes on occasion can get pretty big, if there’s a bit refactor and/or multiple people in the branch. Small enough PRs are a nice goal - it’s a goal that might agree with and exist in part because squash merges on large PRs lose too much. It’s just the real world routinely gets in the way. It’s very easy for someone who needs to do an ‘atomic’ refactor to touch a ton of files. It’s very easy for a planned feature to end up way bigger than intended. You can’t always keep PRs small or enforce it on other people. Sometimes stuff happens, and when it does, sometimes squash merging feels less good than merging a branch with multiple commits. The good news is that it’s always optional. The bad news is that I can’t necessarily babysit or dictate what others do, and some people prefer squash-merging to spending any time doing cleanup on a messy branch.

Re: Git rebase, what can go wrong

#340
post #201

Earlier quoted context omitted.

> why spend time on a ‘nice’ commit history in a (smallish) feature branch when you can squash merge later. Several reasons: * facilitates much better code review discussions * enables use of git bisect to locate bugs * allows for informative commit messages associated with the changes * communicates clearly to future self about why changes were made

> * enables use of git bisect to locate bugs This is really only viable if each intermediate commit on a development branch is intended to be bug free. If that's the standard you and your team work with, that's fine, but it's not usually my standard; in a development branch, I may commit things that don't even compile, let alone work, if it's a good point to commit.

> > * enables use of git bisect to locate bugs

> This is really only viable if each intermediate commit on a development branch is intended to be bug free.

git rebase has an --exec option that allows you to run a command or set of commands for each commit in the branch. You could rebase your development branch before pushing it up for review and ensure each commit passes coffee linting and tests.

Post reply on HN