[HN Gopher] I kind of like rebasing
       ___________________________________________________________________
        
       I kind of like rebasing
        
       Author : nalgeon
       Score  : 146 points
       Date   : 2024-06-20 19:55 UTC (2 days ago)
        
 (HTM) web link (rednafi.com)
 (TXT) w3m dump (rednafi.com)
        
       | quibono wrote:
       | Personally I am squarely in the rebase team although I'm not
       | completely anti-merge. I find the interactive rebase to be so
       | useful that I pretty much never rebase non-interactively. I
       | wonder if part of the reason the merge flow is more popular (or
       | at least it seems more popular) is because native Git tooling
       | around rebasing isn't the best. In fact doing anything more than
       | the simple reword/squash/reorder (like commit splitting or moving
       | chunks between commits) is abysmal. Magit really shines here and
       | makes it a breeze.
        
         | switchbak wrote:
         | I think Git's roots show in its lack of DX. But I'll take it
         | over the horror that was SVN and prior tooling.
         | 
         | Question: how does Magit compare to GitUp? The latter is my
         | benchmark for complex rebases, but I'd love to know if I'm
         | stuck in a local optima.
        
           | joshuanapoli wrote:
           | I haven't used Magit or GitUp, but I really appreciate
           | JetBrains IDE automatic conflict resolver.
        
           | quibono wrote:
           | I've not used GitUp so I'm not sure how much help this will
           | be to you since I can't objectively compare the two. As an
           | example, let's say I want to remove some changes from a
           | commit (and potentially move those into one or more different
           | commits). If I go into the commit and select the chunks I
           | want to revert, I can click `u` and right away I get the
           | revert chunk added into my staging area AND the original
           | chunk added to my working tree. Then I just fix-up the
           | original commit (c F) to remove the unwanted change, and
           | commit the original change - either in a few different
           | commits or possibly just one.
        
         | sjburt wrote:
         | The main issue is that on a longer branch, you have to fix all
         | the rebase conflicts on the oldest commit. Then, if you changed
         | something in the conflict zone, you fix it again on the next
         | commit, because the next commit used to be based on something
         | else. Sometimes git rerere can help with this, but I find it
         | fairly unreliable (could be user error!) If you do a merge, you
         | only need to resolve it all once.
         | 
         | Otherwise I tend to prefer rebase.
        
       | Carrok wrote:
       | > Some like to rebase, while others prefer to keep the
       | disorganized records.
       | 
       | Keeping disorganized records is the only thing you can say in
       | favor of merge commits, and I'm unconvinced that's a positive
       | thing to begin with.
        
         | jaredsohn wrote:
         | I think the argument against rebasing is spending time
         | polishing a PR to have a cleaner history for one feature that
         | will maybe get looked at during review (rather than the final
         | output) vs also making a PR for a second feature during that
         | same time.
         | 
         | And you can eventually have github squash for you anyway.
        
           | yencabulator wrote:
           | Rebase work resulting in atomic commits != squash
        
         | lesuorac wrote:
         | Well disorganized records can still be very useful.
         | 
         | If you're trying to figure out where a bug came from it can be
         | helpful to bisect through all the commits. If you bisect down
         | to 40 file change that's going to be a pain to continue
         | bisecting. However, if you can bisect down to say 5 changes
         | where your bisection fails and 4 of them are because the app
         | fails to build and the 5th is because that's when the bug was
         | introduced that can be very useful.
        
         | joe_fishfish wrote:
         | You can't do stacked PRs without merge commits, not unless you
         | really like conflicts anyway.
        
           | seadan83 wrote:
           | I have never seen stacked PRs work that well in practice. Two
           | reasons:
           | 
           | - Namely there would be review comments on the first PRs that
           | then cause a cascade of merge conflicts in the follow-on PRs
           | 
           | - Somehow reviewers never seem to like the stack of PRs, my
           | experience is they always react with disdain and/or
           | confusion.
           | 
           | There is the counter-question too, why not stack commits
           | cleanly?
           | 
           | A third reason against, not a good reason, but for many
           | developers Git is super difficult (IMO largely a skill issue,
           | not taking the time to learn basic tools that they need
           | everyday; otherwise I have no clue why software developers do
           | not learn their IDEs and VCS tools very well). Stacking PRs
           | requires some Git skills, a simple feature-branch workflow
           | can be a challenge for many..
           | 
           | Ultimately, I think the solution to stacked PRs is to change
           | review policy to "ship/show/ask":
           | https://martinfowler.com/articles/ship-show-ask.html
           | 
           | In other words, if someone is skilled enough to do a set of
           | stacked PRs, the team likely benefits by letting that person
           | merge the stack on their own when each bit is ready and do a
           | post-merge review instead of pre-merge.
           | 
           | (Side-note, my unsolicited perspective: I'm personally
           | convinced that the benefits of linear history is a magnitude
           | more important than all the other peeves & nits combined
           | between merge vs rebase.)
        
             | edfletcher_t137 wrote:
             | > - Somehow reviewers never seem to like the stack of PRs,
             | my experience is they always react with disdain and/or
             | confusion.
             | 
             | Are people sending multiple branches of the stack for
             | review at once? It should only ever be the "bottom" branch
             | out-for-review at any time.
             | 
             | > - Namely there would be review comments on the first PRs
             | that then cause a cascade of merge conflicts in the follow-
             | on PRs
             | 
             | This can still happen in the model above of course as you
             | need to make changes to the bottom branch in response to
             | review comments/requests.
             | 
             | However, as I noted elsewhere, `--update-refs` is an
             | absolute god-send in those situations:
             | https://andrewlock.net/working-with-stacked-branches-in-
             | git-...
             | 
             | It reduces a ton of manual work ( _scaled_ by how many
             | branches you have stacked!) to _one_ operation.
        
               | seadan83 wrote:
               | Multiple at once. Good pointer on `--update-refs`!
               | 
               | I can think of quite a few additional concerns. Overall I
               | think it comes down to how the team wants to handle code
               | reviews.
               | 
               | Personally, I do think if the team is at the level to
               | coordinate and execute on a stack list of PRs, there is
               | little need to incur extra round-trip times for
               | "reviewing" precursor changes and instead focus review
               | time where it is explicitly wanted.
               | 
               | Though, I do indeed like stacked PRs over commit-list
               | because there is more incremental progress, but it does
               | come with some costs. For example, perhaps the last
               | reviewer does not like the overall direction that the
               | cumulative work has led to.
               | 
               | My experience is that at that rate, it's best to let
               | teams decide how they want to operate, formalize somewhat
               | how things are shipped, and bias towards shipping. On the
               | other end of the spectrum, a person quickly glancing at
               | refactoring updates, not having good context on how a
               | given PR fits in - it can almost put into question
               | whether CR itself is entirely a best practice. Hence, I'm
               | a fan of "ship/show/ask". I think it mostly does away
               | with the need for stacking PRs with very little downside
               | (and upside of greater efficiency, CR is spent time
               | reviewing more important code, things that benefit from
               | CR and use the reviewers time well, and makes for a
               | better flow for the author since they can readily merge).
        
           | edfletcher_t137 wrote:
           | Sure you can! In fact you can do magic on stacked branches
           | with `rebase --update-refs` that you can't do with merge:
           | https://andrewlock.net/working-with-stacked-branches-in-
           | git-...
        
       | nailer wrote:
       | Interactive rebase is indeed great, but:                   #
       | Commands:         # p, pick <commit> = use commit         # r,
       | reword <commit> = use commit, but edit the commit message
       | # e, edit <commit> = use commit, but stop for amending         #
       | s, squash <commit> = use commit, but meld into previous commit
       | # f, fixup [-C | -c] <commit> = like "squash" but keep only the
       | previous
       | 
       | ...the CLI git text-document rebase UI is awful. Better command-
       | line rebase UIs are available, or in Fork, I just select a bunch
       | of tweets, right-click, and squash into parent (or use the
       | https://git-fork.com/images/interactiveRebase.jpg where
       | necessary).
       | 
       | If someone complains that CLI git is somehow more pure than using
       | a decent GUI, ask them to rename a stash and time them.
        
         | pluies wrote:
         | Is it that awful? Each option is nicely explained, and the
         | documentation is exactly where you need it, when you need it. I
         | personally found it extremely helpful during my first
         | interactive rebase, and still give it a glance from time to
         | time when I forget the difference between squash and fixup.
        
           | quibono wrote:
           | Provided rewording, reordering and squashing (or fixing up,
           | same thing really) are all you need I think you could argue
           | this is true. Trying to do anything else tends to be a bit of
           | a pain.
           | 
           | On another note, is it possible not to lose the commit
           | description when trying to split a commit? I'm talking about
           | 1) marking commit as `e` to edit it 2) git reset HEAD~ to
           | move back 3) split the change however you want 4) commit
           | again whenever I do it I always lose the original commit
           | message. I'm not sure if it's me being stupid or if there is
           | just no simple way to do it.
        
             | skirmish wrote:
             | "edit" is useful for splitting a single commit into
             | multiple. You couldn't do it with operations you just
             | mentioned.
        
             | 000ooo000 wrote:
             | > is it possible not to lose the commit description when
             | trying to split a commit?
             | 
             | There's 2 cases: 1) extract changes into a commit that
             | comes before the original commit, and 2) extract changes
             | into a commit that comes after the original commit.
             | 
             | In both, instead of editing the commit you want to split,
             | `break` before that commit, and then use `git checkout
             | <hash_of_commit_to_edit> <path_to_files_of_interest>` to
             | pull the changes of interest out into an new, earlier
             | commit. `git checkout -p` is worth a look here.
             | Alternatively if the changes are simple enough, you could
             | use exec instead of break before the target commit.
             | 
             | For 1) you can commit those extracted changes with a new
             | message and then `git rebase --continue`. The original
             | commit will then lack the extracted changes, and have the
             | original commit message. If you did want to adjust it,
             | reword that commit.
             | 
             | e.g.                   pick c62dfe67 1         pick
             | 63dcd748 2         exec git checkout eea68bb8 three.txt &&
             | git commit -m "3"         reword eea68bb8 3+4
             | 
             | For 2) reference the target commit's message as the new,
             | earlier commit's message. Keep in mind that the git
             | invocation in this exec here still supports git aliases so
             | if this was something you do often, you could create an
             | alias for retrieving the next commit message and that last
             | part of the exec could just be `.. && git
             | getnextcommitmessage`
             | 
             | e.g.                   pick c62dfe67 1         pick
             | 63dcd748 2         exec git checkout eea68bb8 four.txt &&
             | git commit -m "$(git log -1 eea68bb8 --format="%B")"
             | reword eea68bb8 3+4
        
         | baq wrote:
         | My only gripe is after 15 or so years with git I still
         | sometimes forget the direction of the time arrow in the
         | interactive rebase.
        
         | formerly_proven wrote:
         | I like that and use it a lot. It's very easy to rearrange
         | stuff.
        
       | switchbak wrote:
       | I had a colleague (smart guy, lots of impressive Ivy League creds
       | after his name) who just _insisted_ that rebasing was evil. There
       | was simply no way to communicate that:
       | 
       | - I can rebase all I want in my own private repo
       | 
       | - Rebasing is fine if no one else thinks they can depend on your
       | branch's history
       | 
       | - You obviously don't rebase master (!) or a branch that you'll
       | collaborate on (not without proper warning at least).
       | 
       | I've seen this attitude more than a few times, and I think it's
       | fear born of ignorance. I just don't get the inability to
       | consider a different perspective.
       | 
       | Edit: formatting.
        
         | recursive wrote:
         | Not only ignorance. I don't generally use rebase myself. This
         | is after having some experience with it. I recently had to help
         | a junior un-wedge his local repo after an attempted rebase went
         | haywire. I reset to the previous commit and replaced the rebase
         | with a merge. The rest of the lifetime of the branch was
         | uneventful. The problems happened because rebasing changes the
         | identity of commits. When merging _that_ result, commits that
         | have previously been merged create conflicts as they now need
         | to be re-merged under the alias of a different commit hash.
         | 
         | If rebasing works for you, I'm not going to try to sell you
         | something. But there are other ways.
        
         | latentsea wrote:
         | As someone in the "merge-only" camp, for me it simply boils
         | down to I don't think rebasing solves anything I view as a
         | problem and as such I just don't care to know anything about
         | it. You can rebase if you want, but don't bother trying to talk
         | to me about it.
        
         | Nullabillity wrote:
         | You _can_ rebase, but you 're still:
         | 
         | - Creating a false history that will be harder for you to
         | understand in the future
         | 
         | - Creating a history that tools will have a harder time dealing
         | with in the future
         | 
         | - Doing so for no actual benefit (in 99% of cases)
        
       | IshKebab wrote:
       | Rebasing is definitely the better option if you can do it.
       | Sometimes it is just too much of a pain resolving conflicts if
       | you are rebasing a branch with lots of commits and there are lots
       | of conflicts. In that case I normally squash and then rebase.
       | Branches where there's enough history to be worth maintaining
       | multiple commits should - 99% of the time - be separate PRs.
       | 
       | The rare exception is when you have multiple people contributing
       | to a branch before it is merged into master, but for obvious
       | reasons you should avoid that when at all possible.
        
         | technojamin wrote:
         | Git rerere basically solves this: https://git-
         | scm.com/book/en/v2/Git-Tools-Rerere
        
         | recursive wrote:
         | > Rebasing is definitely the better option if you can do it.
         | 
         | A bold claim.
         | 
         | > but for obvious reasons you should avoid that when at all
         | possible.
         | 
         | Obvious? I do this somewhat regularly and haven't had a
         | problem. I don't even know what the problem is supposed to be.
         | 
         | Also, I never rebase. Maybe that's why I don't have a problem?
         | When you rebase, commit A becomes commit A'. This becomes a
         | problem when you need to determine whether a particular commit
         | is an ancestor or not. A and A' have different commit hashes,
         | so the identity of the commit becomes somewhat ambiguous.
         | 
         | My workflow is do all development using merge only. When the
         | code review is complete, squash to master. I have found no down
         | sides to this. But I'm not trying to sell it to you either.
        
         | ycombobreaker wrote:
         | > Branches where there's enough history to be worth maintaining
         | multiple commits should - 99% of the time - be separate PRs.
         | 
         | I appreciate that anyone saying this is probably already on the
         | same wavelength as me, but I don't find this to be true for
         | myself. Many times, complex application features end up
         | represented as a series of related, but atomic/meaningful
         | changesets. I want the pull request to make sense as a whole,
         | but expect that code review or audits are easier to accomplish
         | diff-by-diff.
         | 
         | I see it like building a recipe. I want to hide all of the
         | false starts, sloppy mistakes, do-overs, and checkpoints,
         | because they are useless from a historical standpoint. But I
         | still may want to publish a sequence of changes that
         | accomplishes something.
        
           | IshKebab wrote:
           | Yeah that's fine, you can just push the series of commits and
           | then squash them when they are merged. Both Gitlab and Github
           | can do squash merges.
        
       | joshuanapoli wrote:
       | I like rebasing too. When I have any significant change, I
       | usually end up making a mix of clean-up and preparation around my
       | new feature. I like to move the separable parts into separate
       | branches, so that there is less to review per request.
        
       | cocoto wrote:
       | In my opinion squashing is all you need. You keep the organic
       | history on the original branch and the clean and easy to follow
       | history on the master branch. Ideal would be to have a
       | "collapsing" commit instead of squashing for ergonomy.
        
         | simongr3dal wrote:
         | You sort of get that if you're consistent in working on a
         | separate branch, rebasing, and keeping the merge commit when
         | you finally merge.
        
           | recursive wrote:
           | But you can also get it with much less discipline if just go
           | wild merging and doing whatever. And then resolve your master
           | PRs using squash.
        
         | pizza234 wrote:
         | Highly disciplined/structured PRs (with a high rate of atomic
         | commits) merged via merge commit have significant benefits:
         | 
         | - easier to read/analyze
         | 
         | - have better documentation (more isolated git
         | metadata/history)
         | 
         | - are easier to debug (and possible to bisect; it's not
         | possible to bisect a squashed commit).
         | 
         | The problem is that it requires a significant amount of
         | discipline (of course, 100% rate of atomic commits is not
         | possible, but high rate is).
        
           | jaredsohn wrote:
           | >- are easier to debug (and possible to bisect; it's not
           | possible to bisect a squashed commit).
           | 
           | In practice, if bisecting indicates a commit caused the
           | problem you can narrow it down further by checking out that
           | branch and investigating further within that branch (which
           | ideally isn't too large). Also, if you have a highly
           | structured PR then you may need to be careful to ensure that
           | each individual commit passes CI.
           | 
           | At that point you might as well ship each commit via a
           | separate PR. (While in development you can temporarily set
           | the branch for Part 1 as the base for Part 2.)
        
             | fouc wrote:
             | You're assuming it is not an old bug and that the branch is
             | somehow kept around for other developers to re-open months
             | or years later.
             | 
             | A PR for each commit seems overkill. Usually a PR is for a
             | feature, but code-wise, a feature might require several
             | atomic changes. For example: prepare configuration, move
             | files around, add tests, add new code, delete old code,
             | refactor. Each of those could be a separate commit,
             | bringing you to a polished feature with test coverage.
        
               | jaredsohn wrote:
               | Might depend on how companies use git but I just verified
               | I can see commits for PRs from 2017 in my work codebase;
               | could bisect that if needed (although code likely is no
               | longer relevant.)
               | 
               | I think splitting PRs into multiple commits can make
               | sense when there are only 2-3 commits but you're right
               | that it doesn't when there are more than that.
        
             | pizza234 wrote:
             | > At that point you might as well ship each commit via a
             | separate PR. (While in development you can temporarily set
             | the branch for Part 1 as the base for Part 2.)
             | 
             | Absolutely. Indeed, this (independent commit) is a very
             | positive side effect (typical example: separating
             | refactoring commits).
        
           | mrinterweb wrote:
           | Another benefit of not squashing is it encourages devs to
           | think about their commits and is a great opportunity to
           | document what you are doing when they are doing it. If you
           | are squashing 10 commits with junk commit messages (because
           | devs know there is little value in having meaningful commits
           | in what will be a squashed branch), trying to summarize all
           | the changes into a meaningful commit message is hard. It can
           | be valuable to see the intention of atomic commits in git
           | history. The squash branch on merge strategy is just lazy and
           | is counterproductive to having meaningful git history.
        
             | jaredsohn wrote:
             | I prefer to add commentary in the PR on the final changes -
             | what does it do, how does it work, what are some pieces of
             | code I'm less sure of, etc. It is accessible since the
             | squashed commit gets linked to it and that provides a place
             | for people to ask questions.
             | 
             | Also is a lot faster to write and easier to communicate
             | compared to messing around with moving code across commits,
             | ensuring tests pass across them, etc.
             | 
             | Basically I think people care more about what was built and
             | how it works rather than how to split it up step by step
             | (although if the latter is important I can add a comment
             | for that on the PR - although ideally it would have been
             | separate PRs.)
        
               | 000ooo000 wrote:
               | >I prefer to add commentary in the PR on the final
               | changes
               | 
               | That vanishes when you shift forges
        
             | sjburt wrote:
             | I think the problem is that often the order you want it in
             | a clean history is not exactly the chronological order it
             | was developed. Eg you may build out a feature vertically,
             | tweaking the interfaces between the components as you go
             | along. But a clean, atomic git history would probably
             | introduce each component in a finished state in separate
             | commits.
        
             | recursive wrote:
             | This depends on the assumption that going to the trouble of
             | making a carefully curated commit history well documented
             | is even worth the trouble. Sometimes it might be, but I
             | don't think it's a given.
             | 
             | > The squash branch on merge strategy is just lazy
             | 
             | "Lazy" is the negative way of saying "easy" or even "more
             | efficient". "Lazy" implies that the other way is better. Is
             | it? Maybe sometimes.
             | 
             | Am I "lazy" if I walk on my feet instead of my hands? It
             | really is a lot easier.
        
         | erik_seaberg wrote:
         | git log --first-parent shows the merges but not the complete
         | history of each merged branch. git log --first-parent --patch
         | displays all the changes that came with a merge as if it were
         | one big squash commit (in general git log --patch diffs trees,
         | not single commits).
        
       | fleekonpoint wrote:
       | I also like rebasing. Sometimes my squashing cannot be completed
       | without manual intervention, so I'll do a squash merge into a
       | temporary branch instead:                  git checkout main
       | git checkout -b squash-branch         git merge --squash [branch-
       | to-rebase]
       | 
       | At this point I usually git diff the two branches as a sanity
       | check before merging back into main:                   git diff
       | [branch-to-rebase]         git checkout main         git merge
       | squash-branch
       | 
       | I am normally able to squash rebase 99% of the time using git
       | rebase -i main, but doing a git merge --squash into a temp branch
       | has saved me a lot of hassle over the years.
        
       | elijahbenizzy wrote:
       | 100% team rebase -- I think the fear comes from "rewriting
       | history", which sounds scary until you realize that git is
       | entirely immutable data store (through the API at least).
       | Blockchain for the win!
       | 
       | I find merging to be extremely tough to work with -- I don't
       | think I actually got _good_ at git until I learned to rebase
       | entirely.
       | 
       | Also, cherry-picking (effectively an atomic rebase-type) is
       | underrated.
        
         | pdonis wrote:
         | _> git is entirely immutable data store_
         | 
         | Not entirely, since git can automatically garbage collect
         | commits that aren't reachable.
        
         | edfletcher_t137 wrote:
         | > I find merging to be extremely tough to work with -- I don't
         | think I actually got good at git until I learned to rebase
         | entirely.
         | 
         | > Also, cherry-picking (effectively an atomic rebase-type) is
         | underrated.
         | 
         | This this this, all of this.
         | 
         | I never really "got git" until I finally committed to learning
         | how rebase works.
         | 
         | +1 to cherry-picking. Also patch-add (`add -p`).
        
       | notJim wrote:
       | Step 3 can be simplified slightly be doing git fetch && git
       | rebase origin/main. No need to check out the local main.
        
         | blcArmadillo wrote:
         | Or: git pull --rebase origin main
        
           | rednafi wrote:
           | TIL. Thank you.
        
       | xyzzy4747 wrote:
       | If you're using complicated git commands, you're probably doing
       | the wrong thing.
        
         | quibono wrote:
         | I guess it depends on what you mean by a complicated command.
        
       | kkfx wrote:
       | Rebasing is a way to cleanup when a project have a useless
       | history because of too many small commits, badly described and so
       | on. A dangerous way, but still a way.
       | 
       | The issue is another: git does next to nothing to handle forks.
       | We can cherry pick some commits, but there is no easy way to
       | state "we have a project that a certain point in time diverge,
       | keeping some common base, that need to be kept in sync, ignoring
       | the fork specific changes". This led to long and manual three-way
       | merges. No extra help.
        
       | AceJohnny2 wrote:
       | Ah! My people.
       | 
       | I, too, much prefer a rebase-heavy workflow. It allows me to both
       | have a dirty "internal" history and clean up for publication.
       | 
       | As a side-effect, it also makes me comfortable having a mostly
       | linear-history for what I publish, as opposed to a many-branched,
       | merge-heavy one, which I dislike, and makes history confusing.
       | 
       | I reject the argument that a no-rebase, merge-only history
       | "preserves the true history of how commits were created", because
       | I believe that is irrelevant. What is relevant is what the tree
       | looks like once the merge (or rebase) lands.
       | 
       | Should a merge conflict arise, in a rebase workflow the conflict
       | resolution is folded into the rebased commit, so it looks like it
       | was fine all along. In a merge workflow, the fix is in the
       | separate merge commit. In both cases you still have to handle the
       | merge conflict. And in my opinion it is not significant for the
       | merge conflict resolution to be separate from the original commit
       | itself because, again: what's important is the final state of the
       | repo.
        
         | AceJohnny2 wrote:
         | I'll add what should be obvious to any seasoned git user:
         | rebase is only possible for "private" commits. If the commits
         | were published, then merge is the only solution, because
         | otherwise with a rebase you will "change (git) history" and
         | break people's repos that have yours as upstream.
         | 
         | I recommend reading this 2008 exchange between top Linux
         | developers learning to use git, and Torvalds's...
         | characteristic language when talking about rebasing a "public"
         | repo:
         | 
         | https://www.yarchive.net/comp/linux/git_rebase.html
         | 
         | (I'm putting "private" and "public" in quotes because they're
         | really on a spectrum)
        
           | ruraljuror wrote:
           | I like your point. The exception is if the project you work
           | on is itself downstream, in which case maintainers will
           | rebase those "published" commits, probably employing the same
           | technique they use to keep their local development branches
           | up-to-date with the downstream project.
        
           | MrDarcy wrote:
           | In practice it's fine to rebase and force push to your own
           | published branch, even when it's an open PR.
           | 
           | Just mark it draft or otherwise communicate when it's no
           | longer a moving target.
        
             | singpolyma3 wrote:
             | Especially when it's an open PR. That's effectively
             | essential in order to, say, address feedback
        
         | quectophoton wrote:
         | > I reject the argument that a no-rebase, merge-only history
         | "preserves the true history of how commits were created",
         | because I believe that is irrelevant. What is relevant is what
         | the tree looks like once the merge (or rebase) lands.
         | 
         | That's kind of the point though: being reasonably sure that a
         | commit contains a tree that the committer _had seen_ at some
         | point, instead of making up history with commits that contain
         | trees that the committer never saw at any point at all.
         | 
         | When someone rebases `n` commits, experience has taught me I
         | can't trust any commits other than `HEAD`; chances are any
         | commit printed by `git log "HEAD~${n}..HEAD^"` was never
         | checked out by anyone, much less tested at all.
         | 
         | CI pipelines also usually run only against HEAD at the moment
         | of push, so if someone pushes `n` commits, then `n-1` are
         | usually ignored by CI pipeline.
         | 
         | Modifying options for compiler or linter or formatter checker;
         | adding a new dependency or updating an existing dependency's
         | version; changing default options for the project. Stuff like
         | that might make those commits useless, and if someone notices a
         | problem in HEAD after rebase, and decides to fix it, even if
         | the fix is moved to the earliest possible point, nobody would
         | bother re-testing all those n-1 commits after the fix was
         | added, leaving broken commits useless for git bisect.
         | 
         | So I agree that rebase is nice. How most people use it, though,
         | not so nice.
        
           | rednafi wrote:
           | This assumes the rebasing will be done in a shared branch.
           | Two rules of rebasing:
           | 
           | 1. Never rebase a shared branch 2. Never break rule 1
        
             | lmz wrote:
             | No, that describes rebasing and preserving the intermediate
             | commits. Of course, if you squash into one commit at merge
             | time, this won't happen.
        
           | osigurdson wrote:
           | I think most people these days just look at PRs. Everything
           | else is largely noise.
        
             | saagarjha wrote:
             | Not at all. Someone's got to look at your commits in the
             | future when your code breaks ;)
        
               | kazinator wrote:
               | Quite often, that someone is you.
        
           | Buttons840 wrote:
           | In a merge-based workflow you can have commits like "wip" or
           | "before lunch"; no reason to believe those were ever tested
           | either.
           | 
           | I like rebasing but it's ultimately up to the author. Even
           | tools like Fossil, that don't have official history rewriting
           | tools, don't ensure that history has never been rewritten
           | because people can use external tools to do the rewriting
           | (and I've done this).
        
             | martin-t wrote:
             | Use a temporary branch for those. When you come back, undo
             | the commit (git test -- hard if memory serves but i just
             | have an "uncommit" alias) and commit the fully finished
             | work to the real branch.
        
               | Buttons840 wrote:
               | This _is_ destroying the  "real history" though. (Which
               | again, I'm fine with, I like rebasing.)
               | 
               | Two months from now I'm quite likely to say something
               | like "oh yeah, I remember I encountered a bug related to
               | that, I was trying to fix it before lunch". The "wip" and
               | "before lunch" commits are just as likely to be relevant
               | in the future as any other.
               | 
               | It's nice to assume that all commits will compile and
               | pass the tests, but it's sometimes useful to have a
               | snapshot of that weird compiler error you encountered. So
               | much for our nice assumption.
               | 
               | This is why I say it's all up to the author, and if the
               | author likes rebasing, I don't think anyone should have a
               | problem with that. (Don't rewrite public branches, of
               | course.)
        
               | martin-t wrote:
               | There's levels of granularity that matter. You could just
               | as well record all your edits in realtime. Make a script
               | that makes a commit every second or every time you finish
               | editing a line. It might be interesting later, yet that's
               | usually not how people use git. Those changes wouldn't be
               | meaningful units of work.
               | 
               | If you make a commit "wip" or "before lunch" because you
               | want a backup of your work or want to continue on a
               | different computer, then it's not a meaningful unit
               | either. It's OK to throw away.
               | 
               | Most people prefer less granular commits but not to the
               | point of having 1 commit per issue/PR. For example after
               | inheriting someone else's code written in a hurry and not
               | tested, I often end up dividing my work into several
               | commits - first there's a cleanup of all the things that
               | need renaming for consistency, adding docs/tests,
               | removing redundant/unused code, etc. sometimes this ends
               | up being more commits as i reveal more tech debt. Then,
               | when i am confident i actually understand code and it's
               | up to my standards, I make the actual change. This can be
               | again multiple commits. The first and second group are
               | often mixed.
               | 
               | And it's important when it later turns out i broke
               | something - i can focus on the commits that make
               | functional changes as the issue is usually there and not
               | in the cleanup commits which can be 10x larger.
               | 
               | BTW what git is really missing is a way to mark multiple
               | commits as one unit of work so the granularity stays
               | there but is hidden by default and can be expanded.
        
               | rawling wrote:
               | > BTW what git is really missing is a way to mark
               | multiple commits as one unit of work so the granularity
               | stays there but is hidden by default and can be expanded.
               | 
               | Is that not just a non-FF'd, non-squashed merge of a
               | branch?
        
               | martin-t wrote:
               | That's the closest you get today but it means having to
               | make, merge and delete branches all the time. What i
               | propose is something like git squash but that keeps the
               | history internally. It would present as one commit in
               | gitk and other GUIs but could be expanded to see more
               | detail.
        
           | saghm wrote:
           | > That's kind of the point though: being reasonably sure that
           | a commit contains a tree that the committer had seen at some
           | point, instead of making up history with commits that contain
           | trees that the committer never saw at any point at all.
           | 
           | I don't really understand why this would be important. If I'm
           | the one committing, I can rebase however I want to rewrite
           | history before merging, so if I'm super adamant that a commit
           | that looks a certain way exists, I can just make that commit
           | and then put commits around it as needed to ensure that it
           | can be merged with by fast-forward to preserve it. If I'm not
           | the one committing, why should I care about what intermediate
           | states that the person who committed them don't even care
           | about enough to preserve?
           | 
           | To me, the issue seems more that the UX for doing this sort
           | of thing is not intuitive to most people, so the amount of
           | effort needed to get the history rebased to what I described
           | above often ends up being higher than people are willing to
           | spend. This isn't a particulary compelling argument to me in
           | favor of merging workflows though because it doesn't end up
           | making the history better; it just removes most of the
           | friction of merging by giving up any semblance of sane commit
           | history.
           | 
           | (edited to add the below)
           | 
           | > When someone rebases `n` commits, experience has taught me
           | I can't trust any commits other than `HEAD`; chances are any
           | commit printed by `git log "HEAD~${n}..HEAD^"` was never
           | checked out by anyone, much less tested at all.
           | 
           | I definitely agree that generating broken commits during a
           | rebase is not a good thing for anyone, and I'd be super
           | frustrated if I had teammates doing that. At least
           | personally, I make sure to compile and run unit tests before
           | continuing after each step of a rebase after I've fixed
           | conflicts; there's even the `x` option in an interactive
           | rebase to execute a command on each commit (which will halt
           | and drop into commit and allow you to amend before continuing
           | if it fails), which is unfortunately not super well known.
        
           | kazinator wrote:
           | If you want the full history of someone's work, you need all
           | the edits. Including all the times they backspaced over the
           | typo. With down-to-the-millisecond timestamps attached!
        
           | cryptonector wrote:
           | When I rebase I diff after each rebase to check that the only
           | diffs are the ones I intended. So I, the committer, have seen
           | all my rebased commits.
        
         | rictic wrote:
         | Sure it looks nice, but it's a fake history. After a rebase you
         | have commits where no one's ever run the tests, no author ever
         | intended to get the repo into that state. Hell, most likely no
         | one knows if the code even compiles.
         | 
         | It's assuming that that merge conflicts will never be too
         | difficult, and people won't make mistakes in resolving them. If
         | so, too bad, the original commits are lost by the rebase
         | process. (They might or might not be kept in any given clone.
         | No guarantees, good luck trawling through the reflog.)
         | 
         | It's corrupting your database because it makes the UI for
         | exploring it nicer.
         | 
         | This is the opposite of what we should be doing! If the truth
         | is messy we should build better UIs for exploring it. Add
         | additional information on top of the true history, allow people
         | to group and describe commits. Add more information to get the
         | UI that you want, rather than destroying information because it
         | makes things look cluttered.
        
           | AceJohnny2 wrote:
           | > _After a rebase you have commits where no one 's ever run
           | the tests, no author ever intended to get the repo into that
           | state. Hell, most likely no one knows if the code even
           | compiles._
           | 
           | That is the role of the CI system.
        
             | lmz wrote:
             | CI will usually only run the latest commit. Even if commit
             | a, b, and c were all tested, the resulting commits a', b',
             | and c' after rebase would usually only have the last one
             | tested.
        
               | skybrian wrote:
               | Since you shouldn't publish commits that weren't tested,
               | this suggests you should publish only one commit at a
               | time.
               | 
               | (Unless you think "works on my machine" is good enough
               | testing. Sometimes it is.)
        
           | 000ooo000 wrote:
           | >After a rebase you have commits where no one's ever run the
           | tests, no author ever intended to get the repo into that
           | state. Hell, most likely no one knows if the code even
           | compiles.
           | 
           | Only true if the commit author doesn't do so, and it is
           | trivial to do so, either during or after a rebase using the
           | rebase exec command. So given this is a discipline issue no
           | different from a developer authoring a change without testing
           | it, I fail to see how this is "rebase"'s fault.
           | 
           | >it makes the UI for exploring it nicer
           | 
           | Not to imply I accept the "corrupt database" opinion, but I
           | think it's worth saying that aside from the collaborative
           | element of VCS, commits exist for the purpose of exploring
           | past code changes. A practice which improves that seems sound
           | to me.
           | 
           | >we should build better UIs for exploring it
           | 
           | Go right ahead :)
        
             | Nullabillity wrote:
             | > Only true if the commit author doesn't do so, and it is
             | trivial to do so, either during or after a rebase using the
             | rebase exec command. So given this is a discipline issue no
             | different from a developer authoring a change without
             | testing it, I fail to see how this is "rebase"'s fault.
             | 
             | "Undisciplined enough to use rebase, disciplined enough to
             | put in extra effort to mitigate _some_ of the harms of
             | rebase " is an imaginary intersection.
             | 
             | > Go right ahead :)                   git log --first-
             | parent
        
           | singpolyma3 wrote:
           | Nothing prevents people from committing untested code that
           | doesn't even compile without any rebase involved. Even hooks
           | don't help since the incompetent coworkers are just barely
           | smart enough to learn about -n
        
         | danlugo92 wrote:
         | Honestly I dont even do history anymore for small projects, I
         | bisect twice a year tops and I have never evee have had to look
         | at a 3 year old commit to figure out a bug, not that the code
         | could'nt be 3 years old but the blame is so tangled at that
         | point..
        
         | stavros wrote:
         | I've been a developer for twenty four years. I've seen a lot of
         | people have strong opinions about whether to merge or rebase,
         | to squash or not to squash. I haven't seen one single time
         | where it made a difference whether something was merged or
         | squashed, as I've never seen anyone look at commit messages in
         | depth, versus tickets or PRs or bisecting.
        
           | dnadler wrote:
           | Really?
           | 
           | I certainly have used commit messages and seen others do the
           | same. Perhaps this is more an indictment of the quality of
           | the commit messages than anything else.
           | 
           | In my experience, rebase and squash makes it easier to
           | collect work into meaningful groups and thus write more
           | helpful/informative commit messages.
           | 
           | I can think of a few times off the top of my head when I
           | referred back to a detailed commit message in a repo to
           | understand why a change was made.
        
             | stavros wrote:
             | If I'm making a change that people are likely to wonder
             | about, I tend to add comments. Basically, anything that's
             | not obvious tends to get a comment, change or no.
        
           | citrin_ru wrote:
           | I read 'git log -p' often, and linear history makes it so
           | much easier. The same with bisecting. I'm yet to see any
           | practical advantage of not allowing rebase/squash in feature
           | branches. Preserving _all_ history of feature branches is not
           | an advantage to me. The history I care about is the history
           | of the main branch and I don 't want to see it splint into
           | many tiny commits, especially not into commits looking like
           | add/fix/fix/fix/fix where at all point except the last the
           | code is broken.
        
           | klysm wrote:
           | The problem I run into is when a developer merges the main
           | line branch into their feature branch repeatedly to get new
           | changes. Now your branch is completely tangled up and
           | difficult to change
        
             | recursive wrote:
             | I do this like... all the time. At least weekly for the
             | last 5 years maybe? I can't remember a time where this has
             | caused anything to get tangled or difficult.
        
               | klysm wrote:
               | Cherry-picking is harder. Splitting up the branch is
               | harder.
        
               | recursive wrote:
               | I cherry pick occasionally. I don't see how it's affected
               | at all? Edit: If another dev and I both cherry pick the
               | same commit concurrently, that might do something weird.
               | Maybe that's it?
               | 
               | I don't know what splitting up a branch means.
        
               | richbell wrote:
               | https://lore.kernel.org/lkml/CAHk-=wjbtip559HcMG9VQLGPmku
               | rh5...
        
               | recursive wrote:
               | Merges I create from the CLI don't really look that
               | differennt from the ones through some forge UI PR
               | process. I don't know what Linus is getting at. If I was
               | working under someone who had a process like this, I
               | could ask them to clarify what they wanted me to do. I
               | don't have that. And I need to be able to justify all of
               | my decisions. So this isn't useful to me.
               | 
               | I don't doubt that Linus has good reasons for all this. I
               | just don't know what they are. And I don't know if
               | they're applicable to other repos.
        
               | singpolyma3 wrote:
               | ...why? Isn't this exactly what rebase is for? Just
               | plain, boring, non-interactive rebase.
        
           | david_allison wrote:
           | For what it's worth, I often look at commits/commit messages
           | in-depth.
           | 
           | I wouldn't do so if the history were a mess
        
         | rurban wrote:
         | Exactly. The only true history is the clean, properly rebased
         | history with one change per commit, as I want it.
        
         | lr4444lr wrote:
         | Preach, brutha!
        
         | eschneider wrote:
         | I generally prefer a rebase-free workflow (mostly due to my
         | upbringing. Long story...) But other than rebasing shared
         | branches, which (with notable exceptions) is a Wrong Thing,
         | it's mostly up to teams to decide on a workflow that gets
         | things done for them. As long as there's a consensus on how to
         | do things, go with god.
        
         | Nullabillity wrote:
         | > I reject the argument that a no-rebase, merge-only history
         | "preserves the true history of how commits were created",
         | because I believe that is irrelevant. What is relevant is what
         | the tree looks like once the merge (or rebase) lands.
         | 
         | Was the bug introduced by the rebase, or was that code always
         | broken?
        
           | singpolyma3 wrote:
           | Code doesn't exist until it is merged, so these are
           | equivalent
        
       | mrinterweb wrote:
       | Atomic commits can be great. I really prefer to see intentional
       | atomic commits with meaningful messages than 20+ files changed
       | with a commit message: "Feature X".
       | 
       | I am 100% onboard with devs squashing their "lint fix", "test
       | fix", "whatever minor fix to get CI working", "generally
       | meaningless commit to cross the finish line". Also, if devs are
       | working on something they check in a "WIP" commit. It is great if
       | you smash your WIPs into a single meaningful commit. These manual
       | squash strategies require some discipline to clean things up.
       | 
       | I think the "squash branch to a single commit" merge strategy
       | defeats the purpose of atomic commits. Of course devs will be bad
       | at atomic commits if the commits will inevitably smashed to a
       | single commit. IMO squashing branches on merge is a bad version
       | control strategy. I love it when commits are intentional.
       | 
       | One rule I have for any rebasing is, when there may be more than
       | one person using the branch, no more rebasing that branch.
        
         | tkiolp4 wrote:
         | > Atomic commits can be great. I really prefer to see
         | intentional atomic commits with meaningful messages than 20+
         | files changed with a commit message: "Feature X".
         | 
         | The most valuable "feature" of git for me is the "single commit
         | with 20+ files changes". I explain: I have landed in a new
         | codebase, and now I need to add a new feature that would
         | include perhaps a migration and adding a "usecase" and perhaps
         | a "controller" and the corresponding tests. As usual, things
         | are never clear in new codebases (depending on the
         | library/framework used, one might need to add routes to a main
         | routing file, or perhaps touch some configuration yaml file to
         | whitelist the newly introduced endpoint, or perhaps a changelog
         | needs to be kept updated whenever a migration is introduced,
         | etc.). My point is: if I can git blame a line of code of the
         | codebase that's doing already more or less what I want to
         | introduce, I want to see ALL the files that were touched as
         | part of that change. It's a lifesaver.
        
           | mrinterweb wrote:
           | > How many years have you worked in the software industry?
           | 
           | Professionally, 21 years. Seems like you're implying that
           | someone with an opinion that is different than your own is
           | not experienced.
        
             | tkiolp4 wrote:
             | I deleted that part because it sounded the wrong way (it
             | wasn't my intention to question your experience, but a
             | genuine curiosity)
        
           | mrinterweb wrote:
           | Git has great tools. It sounds like you'd want to see
           | everything associated with a merge commit. If what you're
           | looking for is a certain way to view changes, git's built in
           | tooling usually has you covered regardless of commit
           | strategy.
           | 
           | So if you know a commit sha and you'd like to see all of the
           | merged branch changes associated with that commit as a single
           | patch, I cooked up a script that takes a commit sha and finds
           | the merge commit and show all the changes in a consolidated
           | patch.
           | 
           | #!/bin/sh
           | 
           | merge_commit=$(git log -n1 --merges --pretty=format:"%H"
           | $(git rev-list --ancestry-path $1..HEAD --merges -n1))
           | 
           | git show -m -p --stat --format="" $merge_commit
        
         | parpfish wrote:
         | What do you do with the commits that are "incomplete"?
         | 
         | I frequently get halfway through building something, but the. A
         | more urgent project comes up and i need to commit my half-done
         | non-functional work so I can hop onto a different branch
        
           | erik_seaberg wrote:
           | I stash half-baked work to keep it separate from quality
           | commits. When I come back to the stash, I may or may not like
           | where it was going and decide to build on it.
        
             | parpfish wrote:
             | Stashing always makes me nervous.
             | 
             | For some reason it feels ephemeral and I worry that I'll
             | lose the stashed changes like when you accidentally
             | overwrote the copy/paste clipboard
        
               | recursive wrote:
               | Yes, I generally don't use it much, because it forces me
               | to remember that I have stashed work.
        
               | deredede wrote:
               | I used to feel this way because I lost work to `git stash
               | pop` in the past, but there is now a nice feature where
               | if you `git stash pop` and it doesn't cleanly applies,
               | git keeps the stash and I use it more often now.
               | 
               | That said for me the stash is usually used either for
               | temporary stuff (eg taking my current work to another
               | branch) or for things that might be useful to reference
               | later but I will rewrite differently anyways; stuff I
               | want to keep goes into a WIP commit.
        
               | klyrs wrote:
               | Committing everything to a new (temporary) branch, and
               | returning to your current branch, costs nothing and saves
               | the headache of stash's weirdness.
        
           | mrinterweb wrote:
           | I create "WIP" commits, and then I squash those. I squash
           | intentionally to clean up commits that should be together.
        
           | kutenai wrote:
           | I take all "WIP" branches and rebase them as needed onto the
           | 'latest' development. Any continued work on those branches
           | will have to be compatible with all released code, so deal
           | with any issues -- i.e. merge issues during a rebase -- now,
           | rather than later when you try and submit a PR.
           | 
           | As a team leader, I prefer to avoid "a lot of" WIP branches,
           | but I just expect developers to rebase their WIP onto dev,
           | etc.
           | 
           | Oh, and I really really dislike "merging" develop into the
           | WIP branch. This accomplishes the same thing as "rebasing"
           | the WIP branch onto develop, but it leaves a horrible mess
           | behind.
           | 
           | Frankly, I don' give a hoot about some "history" of work. In
           | the end, I care about the unit of work encapsulated in that
           | WIP branch, and that unit must always add on top of develop.
           | Rebase just makes that super clear.
        
           | kcrwfrd_ wrote:
           | I usually use stash for this stuff. But alternatively you can
           | commit and then come back and squash / rebase to clean up the
           | commit history.
        
         | tmtvl wrote:
         | Atomic commits are also really nice for when some stealthy
         | tricky bug appears and you need to git bisect to find out where
         | it was introduced. Ending up with 'the bug got introduced
         | somewhere in this massive commit that touches nearly every part
         | of the system' is not very helpful.
        
         | zikohh wrote:
         | I agree 100%. I also like using FF only. Reviewing commits is
         | part of the code review process - their to title, description
         | and code. If the commits are not atomic and clear I don't
         | approve the merge request (MR); I believe the MR is a full
         | snapshot of what will go to main.
         | 
         | It's so frustrating to see 7 commits for one MR and it's a 10
         | line change.
        
         | GauntletWizard wrote:
         | Branches should be small enough and short lived enough that
         | they are atomic commits. Merge early, merge often, don't break
         | things. Work on small pieces that don't change functionality,
         | The missing part of this is that this causes you to need merge-
         | trains earlier - You'll want to start "stacked" commits that
         | are based on the pieces that are atomic but not merged. That
         | sucks, because the tooling isn't yet great at handling that -
         | It should be possible to mark and auto-rebase all your local
         | branches in that dependency chain,
        
         | deredede wrote:
         | I generally prefer PRs that have multiple atomic commits to be
         | split up in separate PRs. If the atomic commits can't be
         | reviewed separately/introduce non-working states, they are
         | probably too small.
         | 
         | > One rule I have for any rebasing is, when there may be more
         | than one person using the branch, no more rebasing that branch.
         | 
         | That is the one rule to obey for rebasing to be useable at all.
        
       | jaza wrote:
       | I just git commit --amend and then git push -f origin feat_branch
       | all my incremental changes. Saves me having to think of even one
       | word commit messages like "typo" or "renaming". And saves me
       | having to do an interactive rebase later (which basically has the
       | same end result as git commit --amend anyway). Nobody on my team
       | cares about those incremental changes, including me.
        
       | mnahkies wrote:
       | This may be rose-tinted glasses, but I was fine with merges with
       | Mercurial / https://tortoisehg.bitbucket.io/ but subsequently
       | using git (with gitlab/GitHub ) I've been rebase + `--force-with-
       | lease` every time. I'm happy with my current git workflow, but I
       | can't help but feel I'm missing a trick through finding git merge
       | commits so difficult to understand
        
       | juancn wrote:
       | The only issue with rebasing is if someone else has checked out
       | the branch and now they have diverged. It's usually a simple fix,
       | but it can get annoying.
       | 
       | I tend to checkout branches to do code reviews, when changes are
       | complex a diff is not enough, I want an IDE to help me reason
       | about the code (I sometimes even refactor and try different
       | things just so I can understand the code better, so I can make
       | good suggestions).
       | 
       | When I do this, and comment, and the other dev rebases, it's an
       | extra step for me on the next CR cycle.
        
         | kutenai wrote:
         | I train my team on how to resolve this. Every team member is
         | able to resolve a force push onto a branch they have local.
         | 
         | Also, we tend to avoid having multiple people work on the same
         | branch.. so, that's also a thing.
         | 
         | If there was a multi-person development effort, then each of
         | those people would have to have a sub-branch of a main feature,
         | and then they would be rebasing their work onto the 'main'
         | feature branch.. which would ultimately be rebased on to dev..
         | etc.
        
         | rednafi wrote:
         | Never rebase shared branches.
        
       | kutenai wrote:
       | I've looked at the "arguments" for not rebasing and reject them.
       | I've never once thought 'oh shit, I wish I had not rebased that'.
       | 
       | Keeping things neat in the repo has gained me far more than I
       | ever _theoretically_ lost by some conceptual  "loss" of history.
        
       | jauntywundrkind wrote:
       | GitHub uses the committee date, and the committee date changes
       | with rebase. So I almost always --committer-date-is-author-date.
       | Most people don't and it kind of makes their rebases ugly in
       | GitHub, appear to all have happened at time of rebase, which is
       | obviously no good & useless.
       | 
       | Rebasing is excellent. It's a whole suite of tools, unlike merge,
       | which is just merge, for managing history. Rebasing is how I
       | build a sensible history.
       | 
       | I should see if there's some way to set --committer-date-is-
       | author-date by default. Also haven't found a way to make git pull
       | --rebase do c-d-i-a-d.
        
       | 000ooo000 wrote:
       | Everyone's got an opinion on "rebase", and IMO you can safely
       | ignore those that conflate:
       | 
       | * the rebase command, as a means of adjusting commits
       | 
       | * the practice of squashing all commits into a single commit
       | (typically, but not always, via rebase)
       | 
       | * the "rewriting of history", whether on public or private
       | branches
       | 
       | * rebasing on merge vs. creating a merge commit
       | 
       | This article starts by saying they "like rebasing" only to then
       | say
       | 
       | >Git rebase allows me to squash my disordered commits into a neat
       | little one
       | 
       | Rebase allows this practice but you could just as easily `git
       | reset @~` a few times and then `git add .; git commit -m "My big
       | commit"`. Alternatively the author could just `git add .; git
       | commit --amend --no-edit` throughout the task and end up with the
       | same result. To be fair to the author, they later add that they
       | don't always squash to a single commit, but here I'm talking
       | about "rebasing" vs. commit practices. Rebase is just a tool
       | which allows various practices and it's tiresome seeing the same
       | arguments against this nebulous "rebase", when the arguments are
       | actually directed at practices.
        
       | phendrenad2 wrote:
       | Great, just don't force it on me, or grumble when not everyone on
       | the team does it.
        
       | dham wrote:
       | I don't know why anyone cares about this stuff. You can literally
       | do whatever you want on your private branch. If you want to make
       | your life harder, that's cool. Just squash into the main and call
       | it a day. None of this stuff matters anymore, like it did when I
       | started my career.
        
         | klysm wrote:
         | I agree you can do whatever you want on your private branch.
         | Unfortunately I think a lot of developers don't have a solid
         | grasp of what's possible in private, and more importantly what
         | you should do in private vs. on public branches.
        
       | osigurdson wrote:
       | The problem with rebase is it creates a lot of friction when
       | sharing with others. Even if a single dev has two checkouts, it
       | can get confusing ("can I just pull the changes or do I need to
       | reset the branch? - dammit what did I do again? I guess I'll have
       | to review both checkouts history in detail"). Merge based git
       | push / git pull in the other hand, have none of this, thus
       | conceptually much simpler.
       | 
       | Furthermore, since pushes must necessarily overwrite (--force),
       | you actually risk loosing work.
       | 
       | This is all fine and doable but you have to be "on the ball" /
       | paying close attention all the time thus introducing higher
       | cognitive load.
       | 
       | The bottom line is getting work done and making history look good
       | are competing objectives to some extent. There are all kinds of
       | reasons to commit code (I got something working, I want to share
       | something, I need to try this on another machine, etc.). Thus,
       | the only way for commits to appear logical / atomic is to review
       | the current state and refactor it to a logical looking but
       | artificial series of commits. I can't imagine such efforts being
       | useful enough to actually do in most cases. Perhaps even a task
       | better suited to AI.
       | 
       | In reality, the PR is the only commit that anyone cares about.
       | Everything else is mostly just noise. Therefore it would be best
       | if the PR was a first class concept in git vs something only
       | available outside of it (i.e. github).
        
         | klysm wrote:
         | Always use --force-with-lease.
        
           | rednafi wrote:
           | This will only save you if you haven't taken a pull right
           | before pushing your changes to the remote branch. I almost
           | always do this:
           | 
           | ``` git pull --rebase main ```
           | 
           | And then push the changes with `git push origin HEAD`.
           | Pushing with `--force-with-rebase` won't save me from this.
           | 
           | I usually never rebase a shared branch.
        
         | rednafi wrote:
         | Two rules of rebasing that I follow strictly:
         | 
         | 1. Never rebase a shared branch 2. Never break rule 1
        
           | rurban wrote:
           | Always rebase and push --force. Devs who cannot pull --rebase
           | or reset --hard to latest should quit their jobs, and stop
           | whining.
        
             | osigurdson wrote:
             | True Scotsman. Does it or does it not increase cognitive
             | load?
        
           | osigurdson wrote:
           | What is your definition of a shared branch? Is it shared the
           | moment you push it (assuming a github like workflow). Is it
           | shared if you check it out on two separate machines just for
           | yourself?
        
             | rednafi wrote:
             | My definition of a shared branch is the one where only one
             | person is working. It can be your local branch and the same
             | one after you push it to remote. It's still not shared in
             | the sense that only 1 person is supposed to work on that
             | branch.
             | 
             | In this case, you can easily perform rebase and run `git
             | push origin HEAD --force-with-lease` without causing any
             | headache for anyone else.
        
       | peter_l_downs wrote:
       | Enforce squash merging to main and move on with your life. Linear
       | history on main, individual contributors can rebase and merge or
       | format-patch or do whatever they want on their PR branches and it
       | doesn't matter. There are zero downsides to this approach.
        
         | rednafi wrote:
         | Yep. Neither the rebase nor merge workflow negates the benefits
         | of squash-merging to main.
        
       | breatheoften wrote:
       | Strongly pro rebase here.
       | 
       | I sometimes wish I could require squash merging to main so that
       | history on main is fully linear -- however the fatal flaw with
       | doing that is that it becomes impossible to know from git history
       | whether a given branch has actually been merged to main or
       | whether it was abandoned and left to dangle and rot forever. The
       | inability to observe merge state for a given commit increases the
       | effort required to know whether some given piece of work was
       | merged (or at least requires using mechanisms that are not native
       | to git to make such a determination) and complicates cleaning up
       | old local branches after they are merged. If you use a graphical
       | git client then seeing a brunch of old local branches that are
       | already merged everywhere is noisy and distracting. When real
       | merges are done then can easily write a script to remove all the
       | branches that are already merged to main which helps to reduce
       | noise and maintain better focus and faster navigation.
        
       | Taylor_OD wrote:
       | I love rebasing. I know a few people who have disliked it when
       | they first started doing it and most of the time its because they
       | would not rebase into their branches often while working. This
       | made for one big rebase at the end which can be a nightmare.
        
       | kwakubiney wrote:
       | This is exactly what I do at work everytime. The only issue with
       | this sometimes for me is when i rebase interactively and i have
       | my commit message with all squashed commits. So I do a `git
       | commit ---amend` on the squashed commit and tidy up the mess in
       | the message.
        
       | pseudoramble wrote:
       | Not too interested into diving into the debate itself, but one
       | minor point I wanted to add to the article where they count the
       | commits to squash and then do `git rebase -i HEAD~n` is that you
       | can replace this strategy with using the branch you're targeting.
       | So if you're working on a feature branch to merge into `main` you
       | can update the local main branch first, then punch in `git rebase
       | -i main` and it'll handle finding all the commits for you.
       | 
       | I'm sure there's even more clever ways to do this, as it always
       | seems like there's more when it comes to git. This is just the
       | most intuitive way I've seen so far, and so it sticks in my mind.
        
         | hansvm wrote:
         | And a fairly quick way to do the same sort of thing is `git
         | fetch && git rebase -i origin/main`. You never bother updating
         | `main` because you kind of don't care for the task at hand.
        
           | pseudoramble wrote:
           | True, good point. Makes sense! Thanks for the improvement!
        
       ___________________________________________________________________
       (page generated 2024-06-22 23:01 UTC)