[HN Gopher] Take Advantage of Git Rebase
       ___________________________________________________________________
        
       Take Advantage of Git Rebase
        
       Author : HieronymusBosch
       Score  : 103 points
       Date   : 2022-10-06 13:07 UTC (9 hours ago)
        
 (HTM) web link (about.gitlab.com)
 (TXT) w3m dump (about.gitlab.com)
        
       | rmetzler wrote:
       | I was waiting for ,,Gitlab releases a UI for rebase -i in MRs".
        
         | dnsmichi wrote:
         | Thanks, great idea. Added a comment into the feature proposal
         | in https://gitlab.com/gitlab-
         | org/gitlab/-/issues/273250#note_11... - suggest upvoting and/or
         | subscribing to notifications.
        
       | zwieback wrote:
       | Years ago I really liked rebase, now I never use it. I don't know
       | why, though, one of those mysteries of the brain.
        
       | secondcoming wrote:
       | Been using git for 10 years now, never rebased, never had an
       | issue.
        
         | goalieca wrote:
         | You've never used gerrit then. That tool is entirely designed
         | around rebasing with merges as a rare event.
        
           | recursive wrote:
           | Nor have I heard of it. (not OP)
           | 
           | There are probably tools built around merging too.
        
             | goalieca wrote:
             | Gitlab and github are built around merge-requests and
             | gerrit around rebasing/amending. I strongly prefer
             | gitlab/github workflows.
        
         | chris_wot wrote:
         | You've never lived.
        
           | ayewo wrote:
           | Can't tell if you are joking or not, but if you are not
           | that's a bit too mean. At the end of the day, they are merely
           | tools.
           | 
           | > _You 've never lived._
        
             | chris_wot wrote:
             | I use it all the time.
        
         | Jwarder wrote:
         | I think it depends on what problems you want git to solve for
         | you.
         | 
         | Some people like having the context from the complete the
         | history of little commits without the risks of rebase breaking
         | something.
         | 
         | Some people like using rebase to group all changes needed for a
         | feature into isolated(ish) commits.
         | 
         | Some people just like the aesthetics of a straight master
         | branch without the clutter of little "corrected typo" or "fixed
         | bug for real this time" commits.
        
         | chriswarbo wrote:
         | Been using git for 15 years now. Occasionally rebased, usually
         | had an issue ;)
        
       | placatedmayhem wrote:
       | Rebase has become so integral to my workflow, it's hard to
       | imagine living without it. I intentionally avoid merge commits,
       | including configuring git pull to rebase rather than merge. I
       | find it so much easier to commit a bunch of tiny iterations while
       | doing local testing, rebase and squash them, then post them for
       | review. As a bonus, I frequently push after each of those small
       | commits to a feature branch so I don't have to worry about losing
       | work if my drive dies.
        
         | agumonkey wrote:
         | then there's autosquash and similar
         | 
         | honestly the commit graph as a first-class value yields a lot
         | of ideas in my mind, we should be investigating compute at the
         | subtree layer more often.
        
         | rrwo wrote:
         | > Rebase has become so integral to my workflow, it's hard to
         | imagine living without it.
         | 
         | Same. I use it to reorganise branches before submitting change
         | requests or merging:
         | 
         | - Combing or splitting commits so that each commit contains a
         | small unit of a logical change
         | 
         | - Reordering commits to related changes are near each other
         | 
         | - Reordering commits so changes that are depended on by later
         | commits occur earlier.
         | 
         | - Rewording commit descriptions to have a lengthy explanation,
         | if needed
         | 
         | - Removing small commits that fix minor typos
         | 
         | It's a great way to turn the commit history of a project into
         | one of logical changes, rather than a simple temporal log of
         | every change.
         | 
         | (I had a colleague who was so used to CVS and couldn't get his
         | head around not using version control as a time tracking
         | device.)
        
         | rubyist5eva wrote:
         | Personally, I actually stopped using rebase or advocating it's
         | use (because noobies mess up their history all the time with
         | it). I just commit whatever, then when the code is merged to
         | trunk/dev/master/whatever I use `merge --squash`.
         | 
         | Reviews are very rarely happening on the commit level, so
         | having lots of small "meaningless" commits (lint fixes, fix
         | spec, add thing) hasn't been an issue but having squashed merge
         | commits (effectively a rebase that squashes everything) has
         | made release management so much easier for our team.
         | 
         | It also has the benefit of just less cognitive overhead of
         | micro-managing my feature branch commits that are WIP or
         | currently in-review.
        
           | dabears wrote:
           | This is my workflow as well, it's great. Github is configured
           | so merging a PR into master will automatically produce a
           | squashed commit.
           | 
           | My rule of thumb, always rebase unless you hit a series of
           | merge conflict while rebasing. Then either merge, or squash
           | your branch then re-run the rebase.
        
             | rubyist5eva wrote:
             | We require linear history on our shared mainline branches
             | so the squash workflow works great for us using Github as
             | well. Another benefit is the "show changes since last
             | review" option when reviewing a PR - it's been a while but
             | I'm not sure if this is possible with a rebase-based
             | workflow.
        
           | jokab wrote:
           | Thanks. I thought it was just me.
        
         | gregmac wrote:
         | > Rebase has become so integral to my workflow, it's hard to
         | imagine living without it
         | 
         | I'm the same. I commit frequently. A lot of those end up being
         | `--amend`, but a lot of time I will rebase and
         | squash/reorder/etc. In fact I'd say the majority of time I push
         | changes I've rewritten my local history at least once.
         | 
         | According to any git history you'd find from me on the server,
         | you'd think I never accidentally commit syntax errors, break
         | unit tests, and that when I do big structure changes or
         | refactors I get it the way I want it on my first attempt.
         | 
         | > including configuring git pull to rebase rather than merge
         | 
         | It annoys me a bit this isn't the default -- at least for teams
         | that work from a single centralized git repo (eg: almost all
         | corporate dev, and the majority of open source). I've done it
         | for years and have never had any issue with it.
         | 
         | It doesn't rewrite anything but your local (non-pushed)
         | history, which is totally fine. (Unless you are working with
         | multiple remotes, in which case it causes chaos, which I think
         | is why it isn't the default).
         | 
         | Are there other drawbacks?
        
         | robertlagrant wrote:
         | This might be obvious, but it's worth checking out git commit
         | --amend. Then you can be regularly committing, but to the same
         | commit.
        
           | usr1106 wrote:
           | --amend if you have a modification to your most recent
           | commit.
           | 
           | --fixup if you have a modification to an earlier commits
           | 
           | rebase --autosquash amend the fixup(s) to the commit(s) they
           | belong too.
           | 
           | (Of course you need to know what you doing. Otherwise you
           | create conficts tedious to resolve in the rebase)
        
           | dnsmichi wrote:
           | Depending on the workflow and collaboration in branches in
           | teams, amending may not be ideal. Amending changes to an
           | existing commit will generate a new sha checksum, thus
           | resulting in a diverging history if the branch is often
           | pushed to the remote Git server. That's one of the rare cases
           | where "git push --force" makes sense but also requires
           | awareness for other collaborators on the branch - they need
           | to run "git fetch && git reset --hard origin/branchname"
           | every time, and best "git stash" to temporarily remove any
           | local changes, with running "git stash pop" afterwards.
           | 
           | One reason to regularly push commits can be to trigger CI/CD,
           | security scanning and dev/staging deployments or review apps.
           | 
           | GitLab team member here - before joining GitLab in 2020, I
           | was a Git/GitLab trainer.
           | https://www.netways.de/en/blog/2018/05/24/releasing-our-
           | git-...
        
             | tspike wrote:
             | I've completely replaced my use of --force with --force-
             | with-lease. It does the same thing, except it will abort if
             | the upstream branch has been updated since your last pull.
             | This pretty much prevents the concerns about clobbering
             | others' work.
        
               | dnsmichi wrote:
               | After reading this comment about "git push --force-with-
               | lease" in https://stackoverflow.com/a/53011907/1821348 my
               | workflows with "git fetch" first would not work with "git
               | push --force-with-lease", behaving as if "git push
               | --force" was run. Theoretically - I need to do some
               | testing here.
               | 
               | Thanks for the pointer into learning something new :)
        
             | robertlagrant wrote:
             | For sure, it doesn't work with every workflow. But I think
             | it would for the OP's described workflow.
             | 
             | And I am currently waiting for my GitLab backpack for
             | contributing something (very small, but apparently it
             | counted!) so thank you to the team for that!
        
               | dnsmichi wrote:
               | Thanks for sharing your ideas, appreciate the thoughts to
               | learn new perspectives :-)
               | 
               | And also thanks for contributing, every contribution
               | counts and helps :-) Maybe see you at a future hackathon
               | :) https://about.gitlab.com/community/contribute/
        
           | shagie wrote:
           | --amend would interact with the remote system poorly if
           | there's a push with each commit.
        
             | sjburt wrote:
             | You have to force push, but you have to do that when
             | pushing a rebased branch as well. In either case it's a
             | history rewrite. It's not a big deal unless other people
             | have pulled that branch--if they have they will need to
             | reconcile things on their end as well.
        
       | DrBenCarson wrote:
       | Easily the most underutilized and poorly understood part of the
       | typical git workflow
        
       | boleary-gl wrote:
       | I don't know if Christian would go this far, but I actually put
       | this into my ~/.gitconfig so that I'm _always_ rebasing
       | 
       | [pull]
       | 
       | rebase = true
       | 
       | edited for line spacing
        
         | davecamp1717 wrote:
         | Yeah, I wish this was the default functionality in git, to me
         | it never makes sense not to want to rebase when pulling.
        
         | augusto-moura wrote:
         | Just a nit on the HN comment, you can indent the lines 2 spaces
         | so that it shows up as a code block, it should maintain the
         | correct spacing/line wrapping and it uses a monospaced font as
         | well                 like this
        
           | boleary-gl wrote:
           | Thanks - today I learned
        
           | dnsmichi wrote:
           | Today I learned, thanks a lot!
           | 
           | Created a MR for the Developer Evangelism Hacker News
           | handbook to add this formatting tip, and some more
           | https://gitlab.com/gitlab-com/www-gitlab-
           | com/-/merge_request...
        
         | dnsmichi wrote:
         | You are more brave than I am - I have it explicitly disabled
         | :-) https://gitlab.com/dnsmichi/dotfiles/-/blob/main/.gitconfig
         | 
         | When I pull and it runs into a merge conflict, I want to see
         | that error/log on the CLI. Reason: Sometimes the automated
         | pull-rebase takes a very long time to resolve conflicts after
         | each step. I prefer to first run                 git fetch
         | git diff branchname origin/branchname
         | 
         | and then decide my strategy :)
         | 
         | Bit off-topic but since we share .gitconfig tips - I upgraded
         | to a recent Git version and enabled the "git push" option to
         | setup tracking automatically. No more "git push -u origin
         | branchname" actions.
         | https://gitlab.com/dnsmichi/dotfiles/-/blob/main/.gitconfig#...
         | [push]        autoSetupRemote = true
        
         | silverwind wrote:
         | `pull.rebase` should be the default just because it avoids the
         | problem of merge commits.
        
         | greatpostman wrote:
         | Wow did not know this existed. I'll add it to my config
        
       | MilStdJunkie wrote:
       | In my personal experience rebase made ISO9000/AS9000 gatekeepers
       | twitchy. Even to the extent that they'd tell the Overlords "Do
       | everything in Perforce, or else".
       | 
       | And then the Overlords shut down all the VCSs because "this isn't
       | a software company". Then everyone sneaks around using weird
       | homebrew portable tracking widgets, or, more often, just gives
       | up.
       | 
       | Is rebase handy? Oh yeah.
        
       | tuckerpo wrote:
       | I love rebase. It allows for a Draft PR workflow where you can
       | have your WIP out in the open for a big project, and then clean
       | it all up via rebasing right before asking for reviews. Just
       | don't rewrite history on master. :^)
        
       | dbbk wrote:
       | Every PR we have in GitHub is merged with a squash, so I'm kinda
       | missing the value proposition here. Is it really crucial for each
       | commit to be a nice clean unit of work?
        
         | throwaway_au_1 wrote:
         | Never understood the appeal of squash commits at merge time,
         | assuming the PR contains atomic, logical commits (all bets are
         | off if your team's PR process accepts ad hoc commits..). You
         | lose the utility of git bisect, conventional commits, etc, and
         | also have larger, noisier commits forming your
         | history/documentation. Is there a benefit to squash commits
         | other than allowing developers to forget about that as they
         | work? I may be biased against squash commits as I have spent
         | enough time diving through garbage commit history to figure out
         | bugs/Chesterton's fence that good commits as documentation
         | appeals to me.
        
           | ivanche wrote:
           | I much prefer to see one squashed commit over an endless
           | stream of "fix typo", "small fix", "fixup", "forgot XYZ"...
        
             | tcoff91 wrote:
             | Don't approve PRs that have those commits.
             | 
             | A PR doesn't necessarily have to be a single commit to be a
             | good PR. Sometimes, it makes sense for a PR to have several
             | atomic commits.
             | 
             | Those tiny messy commits should be fixed-up into the atomic
             | commit that they are fixing.
        
           | phailhaus wrote:
           | > assuming the PR contains atomic, logical commits
           | 
           | This is impossible to enforce or guarantee at scale.
           | Squashing PRs, though, is practically fool-proof: PRs already
           | represent a single, atomic unit of work that passes all CI
           | checks and is safe to merge. No such thing is true (or should
           | be!) of individual commits within that PR. Whether we like it
           | or not, a branch commit really only represents a "save point"
           | for a developer.
        
             | kbr- wrote:
             | What you say is impossible, we pretty successfully apply at
             | ScyllaDB (see
             | https://github.com/scylladb/scylladb/commits/master).
             | 
             | I'm not sure 100% of the commits compile & pass all tests -
             | there may be some mistakes - but generally we're in a
             | pretty good state, and the clean git log is being
             | successfully used for bisecting.
             | 
             | If you want even larger scale - if I understand correctly,
             | the Linux kernel practices a similar thing, which is where
             | we got this practice from (ScyllaDB founders came from
             | kernel development). And since Git was originally created
             | to help developing Linux - that's where you want to look
             | for good practices.
        
             | WorldMaker wrote:
             | You can get the same guarantees without squashes with {log,
             | bisect, blame} --first-parent and merge --no-ff (force all
             | PRs to make merge commits). You can preserve more of the
             | graph and use it to revisit "inside" of PRs when necessary.
        
               | tcoff91 wrote:
               | So much this. Everyone needs to learn about --first-
               | parent, it makes git log, git bisect, etc... so much more
               | powerful and prevents people from just squashing PRs into
               | giant mega-commits that make the history so much less
               | useful.
        
               | WorldMaker wrote:
               | I keep joking that all we need is one good Git GUI to go
               | viral that defaults to --first-parent in every view and
               | we might eventually convince more people they don't need
               | to squash/rebase as much. One of these days I may even
               | take the joke far enough along to prototype something.
        
           | debaserab2 wrote:
           | You don't lose that much utility of git bisect unless your
           | PR's are typically large.
           | 
           | One thing squash and merge does is make reverting trivial.
        
             | tcoff91 wrote:
             | You can revert a merge commit.
        
         | dnsmichi wrote:
         | GitLab team member here, putting my personal hat on - from my
         | experience in using different Git workflows since 2009, a
         | smaller clean unit of work can help with debugging and
         | troubleshooting. It also provides a way to new team members and
         | contributors to understand the thought process and ideation to
         | implement a new architecture, apply performance fixes, add
         | documentation, work with tests, additional fixes, until its
         | final release. Most of this can be tracked within a MR/PR and
         | the history of code reviews, etc. - even after the merge and
         | squash and Git branch delete, not trying to argue with this
         | functionality. :)
         | 
         | From the Git CLI, without any reference to Git* platforms, it
         | is not so obvious when searching for a commit that introduced a
         | bug, e.g. using "git bisect" for binary search. Reading a
         | 10,000 lines git diff can be harder than a smaller commit that
         | also explains the reasoning in the commit message. Speaking
         | from own experience and programming mistakes in a small team,
         | focussing on clean commits and a good history tremendously
         | helped in stressful debug situations. Until you hit a compiler
         | regression bug, but that's a different story then ;)
         | 
         | I'm personally still very fast on the Git CLI, but I also know
         | that there are a variety of CLI and UI tools out there that can
         | help with analysing large Git commits. Potentially in the
         | future also AI assisted that tell us which change a diff caused
         | a performance regression in a release 5 months later. Or we
         | don't need it at all because Observability driven development
         | enabled to see these problems before merging and code reviews,
         | e.g. the memory leak but only when DNS fails. True story from
         | ~2016, more in my KubeCon EU talk at
         | https://www.youtube.com/watch?v=BkREMg8adaI and project at
         | https://gitlab.com/everyonecancontribute/observability/cpp-d...
        
           | mixmastamyk wrote:
           | If your merge request is gigantic, that's the problem. Easier
           | to keep those focused than obsess about every commit.
        
             | dnsmichi wrote:
             | True, thanks. Some workflows can require larger merge
             | requests, having the platforms and tools that enable
             | smaller iterations help reduce (or eliminate) them though.
        
         | agumonkey wrote:
         | you keep the feat branch but only add single merged commit to
         | master ?
        
         | giancarlostoro wrote:
         | I think it really depends on whose doing the commits, I've
         | mostly worked with people who wont commit things that don't
         | work so you see a lot less commits than you would expect. I
         | prefer commits to be iterative and I prefer to see that if
         | possible. I rather see 100 commits across dozens of files per
         | commit vs 1 commit for 500 files.
        
           | P5fRxh5kUvp2th wrote:
           | plus, you can tell who doesn't use git bisect because they
           | prefer a single large commit across 500 files to keep history
           | clean.
           | 
           | As opposed to a series of small commits, that would make git
           | bisect actually useful.
        
             | mixmastamyk wrote:
             | Your features are not broken down enough if one ticket
             | requires hundreds of changes.
        
               | giancarlostoro wrote:
               | This is a solid argument. Except in cases where you're
               | upgrading everything in a small to mid sized codebase
               | that needs a major dependency updated that affects
               | everything from syntax to other things, and cannot be
               | done discretely.
        
             | dmatech wrote:
             | Why can't we just have some kind of "virtual squash" where
             | the commits are preserved, but they're grouped together so
             | you could view it as a single squashed commit if that's
             | preferable?
        
               | lixtra wrote:
               | Why not keep commits as the atomic element and use
               | (release) tags if you want a coarse overview what
               | happened?
        
               | wnoise wrote:
               | That's a semi-linear history merge.
        
           | warmwaffles wrote:
           | Depends on the situation entirely.
           | 
           | If I see a ton of commits like "fixing formatting" or "oops",
           | I want those squashed away into proper commits.
           | 
           | If the changes you make are atomic in their own right and I
           | can check out that commit, compile it, then run tests, and it
           | passes. That's perfect. It works good for git-bisect, but the
           | trick is to get everyone on board in the project to do that.
           | 
           | For public libraries I maintain, it's squash merges all the
           | way. I like a clean history and the ability to check out that
           | commit, compile, test, and run cleanly is perfect.
        
             | giancarlostoro wrote:
             | > If I see a ton of commits like "fixing formatting" or
             | "oops", I want those squashed away into proper commits.
             | 
             | Every team I'm in I strongly advise against such commits
             | honestly. They don't help anyone, I emphasize being able to
             | find things you changed if you need to find them. You can
             | even enforce a format for commits.
             | 
             | Funnily enough, I saw a wave of "fixes bug" "now really
             | fixes bug" that got auto rejected by some commitcop utility
             | at a former job, the guy was freaking out cause it wouldnt
             | take all his changes. I guess they wanted to force him to
             | stop doing such awful commit messages.
             | 
             | Commit messages should be useful and historically
             | descriptive.
        
               | warmwaffles wrote:
               | > Every team I'm in I strongly advise against such
               | commits honestly. They don't help anyone, I emphasize
               | being able to find things you changed if you need to find
               | them. You can even enforce a format for commits.
               | 
               | Same with me, but people still ignore it.
        
           | [deleted]
        
         | stinos wrote:
         | In my opinion, yes, but like everything else it's not a hard
         | rule. But especially for refactoring I really really want to
         | read a comprehensive story of granular enough (but not too
         | much) commits which logically follow each other, instead of a
         | code dump with commit message 'bugfix'. That, plus just looking
         | at the default graphical representation most git tools out
         | there produce for merges vs simple rebased history: yes I'll
         | take the latter.
        
         | Nagyman wrote:
         | As always, it depends. Especially for large PRs, I will go
         | through the effort of rebasing to help the code reviewer so
         | they can view key commits rather than a mile long scroll-fest
         | on the GH "Files Changed" tab. It's about being a good co-
         | worker and facilitating faster reviews.
        
         | blktiger wrote:
         | I sometimes prefer a rebase to a merge when pulling in changes
         | from some other branch. It can be easier to deal with several
         | smaller merges than one big one which a rebase accomplishes.
         | This is not always true of course, so I usually start with a
         | regular merge and if it's sufficiently complex or hard to
         | untangle then I give a rebase a try to see if things get
         | easier.
        
       | sidlls wrote:
       | Git is in general a terrible tool: I've always thought of it as a
       | shining example of where "worse is better" ought to have been
       | applied. Rebasing is one of its worst features. For non-trivial
       | changes, anyway, it is often just a way to add complexity and
       | messiness to what should be a simple workflow. And the benefits
       | aren't at all as clear as its advocates contend.
        
         | mixmastamyk wrote:
         | Yes, and these folks are never around when you try rebase and
         | get a forty file conflict and have no idea how to get out.
         | Happened to me several times when I fell for one of these
         | articles.
         | 
         | You know what works almost every single time? With tiny
         | conflicts if any? Merge + squash on gitlab.
        
           | Extigy wrote:
           | If a rebase goes wrong and you want out you can run,
           | git rebase --abort
           | 
           | to return to where you were beforehand.
           | 
           | I find that git is actually very good at explaining what is
           | going on and what you should do next by just running git
           | status in the middle of some process like rebasing and
           | reading what it says.
           | 
           | Even if it all goes _really_ wrong the git reflog has always
           | saved me.
        
       | jbergknoff wrote:
       | If I've already reviewed a PR and the author makes further
       | changes, I definitely prefer to review an add-on commit. If the
       | history is rewritten/rebased, then IME the entire PR needs to be
       | re-reviewed from scratch. If we're talking about a <10 line
       | change, then, by all means, rebase to your heart's content. With
       | anything more complicated than that, rebasing a branch that's
       | already been looked at can be disruptive and I'd strongly
       | recommend against it (though squash-and-merge after review is
       | fantastic).
        
         | Shatnerz wrote:
         | I didn't actually read the linked article but I see it is from
         | GitLab. GitLab makes it easy to view the diff between versions
         | of an MR even if it includes rebases.
        
           | matijs wrote:
           | GitHub does the same. There is a compare button that appears
           | after a force (with-lease) push of a rebased branch.
        
           | johnnypangs wrote:
           | How does that feature work in Gitlab? I also use it along
           | with a rebase policy at work and sometimes have that issue.
        
             | nemetroid wrote:
             | https://docs.gitlab.com/ee/user/project/merge_requests/vers
             | i...
        
         | jasonlotito wrote:
         | Are there CR tools that don't display the diffs between
         | rebases? Seems like a tooling issue more than anything.
        
         | kotborealis wrote:
         | Some code review systems, like gerrit, actually encourage this
         | workflow: you can easily view diffs between commit versions
         | ('patchsets').
        
         | rubyist5eva wrote:
         | In your view if a PR is not rebased but trunk is merged into
         | it, does that warrant a full re-review? The end result is
         | functionally the same as a rebase.
        
         | thibran wrote:
         | Changes should be added with additional commits. When the
         | review is complet, the code should be rebased and merged (git
         | merge --ff-only my-reviewed-banch). This leads to a clean git
         | commit history and an easy review process.
        
         | seba_dos1 wrote:
         | > then IME the entire PR needs to be re-reviewed from scratch
         | 
         | Why? What's the difference? You can still diff the previous
         | version of the PR with the current version and end up with the
         | same thing that an add-on commit would give you, but ready to
         | merge as-is.
        
         | Arch-TK wrote:
         | Does your project have a policy of compiling and running (and
         | e.g. tests passing) at EVERY commit?
         | 
         | I can't imagine being able to easily enforce that without
         | asking people to edit the correct part of their commit. It's
         | maybe more difficult with gitlab/github interfaces where
         | changing the middle of a sequence of commits will not render
         | very well, but in email based workflows it works fine.
         | 
         | On the other hand, being able to bisect a project without
         | having to worry about whether an unrelated issue is causing you
         | to traverse the wrong branch of the bisect is an enormous
         | advantage compared to the minimal effort required of keeping
         | track of a modified (rebased) commit in the middle of a set of
         | commits under review.
        
           | Supermancho wrote:
           | > I can't imagine being able to easily enforce that without
           | asking people to edit the correct part of their commit.
           | 
           | I imagine something something githooks. However it might be
           | enforced, it seems like a miserable way to develop.
        
           | rjmunro wrote:
           | You can now use --first-parent when you bisect to ensure
           | bisect doesn't go into branches but stays on the main branch.
           | 
           | https://git-scm.com/docs/git-bisect#Documentation/git-
           | bisect...
        
             | Arch-TK wrote:
             | I don't see how this solves the problem of patches which
             | fix up previous patches. This workflow doesn't require
             | using merges, but it will introduce situations
             | (irrespective of whether you use --first-parent or not)
             | where patches fix previous patches potentially leaving a
             | gap where code doesn't compile, doesn't run, or doesn't
             | pass tests.
        
       | chris_wot wrote:
       | The one thing I'd like to do is to insert a commit between two
       | commits, then edit this and then make a modification.
       | 
       | Currently I create a text file, add this, then move this up to
       | where I need to insert it and edit this commit.
        
         | alisonatwork wrote:
         | You can also just `git rebase -i` and set `e` (edit) on the
         | commit before the one where you want to insert a new commit.
         | Instead of doing `git add .` and `git rebase --continue` like
         | you normally would to squash your changes into the commit
         | you've stopped to edit, you can just `git add .`, `git commit
         | -mwhatever` and then `git rebase --continue`. Now you have new
         | commit "whatever" in between the one you stopped to edit on and
         | the next one.
        
         | throwaway_au_1 wrote:
         | It's not clear to me exactly what you mean. Based on adding the
         | text file, which sounds like you're creating a placeholder
         | commit, you might not know about 'git commit --allow-empty'
         | which may serve you better.
         | 
         | Not exactly sure of your order of events wrt inserting a commit
         | and editing it (I.e. edit commit message? Or changes?) and
         | modifying it (I.e. see previous) but am happy to try and help
         | if you want to flesh out your example a little more.
        
           | throwaway_au_1 wrote:
           | To speculate, maybe you haven't heard of fixup/squash.
           | 
           | E.g. Commit 1 Commit 2 Commit 3
           | 
           | Using an empty fixup commit, e.g.
           | 
           | git commit --allow-empty --fixup=commit2hash
           | 
           | You would end up with
           | 
           | Commit 1 Commit 2 Commit 3 fixup! Commit 2
           | 
           | Which will adjust automatically (when starting interactive
           | rebase with autosquash) to
           | 
           | Commit 1 Commit 2 fixup! Commit 2 Commit 3
           | 
           | You could then simply change the rebase 'fixup' instruction
           | to 'reword' to edit/remove the 'fixup!' part of the message,
           | or 'edit' to continue the rebase uo until that commit and
           | then stop.
           | 
           | That said, again, not clear on your use case but maybe that
           | might help you or another reader.
        
       | mattpallissard wrote:
       | Keeping your commits as separate units of change, and leveraging
       | rebase/ff-only is worth is simply so you can do stuff like the
       | following.                   git revert $(git rev-list
       | COMMIT43^..COMMIT123 -- path/to/thing)
       | 
       | I've been on teams where everyone _hates_ what a stickler I am
       | about good VCS hygiene until they realize something that looks
       | like it's going to be a big pain in the ass at first glance is
       | doable with a one liner.
        
         | mixmastamyk wrote:
         | What is this a solution to?
        
           | mattpallissard wrote:
           | Reverting a range of changes for a given path.
        
       | vincentkriek wrote:
       | I sometimes run into rebases where solving merge conflicts 3
       | times is hard. Replaying 3 commits for instance, where merge
       | conflicts are present in each one. In the first I need to fix the
       | merge conflict but remind myself that there are more commits
       | following this that change this behavior.
       | 
       | With a merge commit I am fixing the resulting work on both
       | branches, which is easier than merging the in progress state in
       | the current branch.
        
         | abeyer wrote:
         | Isn't that exactly what rerere is for?
        
         | tcoff91 wrote:
         | In these scenarios, I think it's better to use merge commits.
         | 
         | Anytime resolving conflicts becomes pretty intense, where
         | you're feeling like there's a significant risk of introducing a
         | bug in the resolution process, I think it's better to use merge
         | commits because then it's preserved in the merge commit how the
         | merge conflict was resolved. If things were done incorrectly,
         | you can trace it back to the merge commit and analyze it and
         | you don't potentially lose important intermediate state that
         | you might need to recover.
         | 
         | On the other hand, If you're touching the same code in 3
         | separate commits, then perhaps they shouldn't be separate
         | commits. In these instances, I often do 2 rebases: 1 to squash
         | the commits without reparenting them, and then another to
         | reparent the squashed commit onto the upstream branch.
         | 
         | Also, if you use merge commits for merging PRs, it's easy to
         | cut through the noise of the commit graph by using git log's
         | --first-parent option. Once you are using this, it's a lot less
         | important to keep an ultra-tidy commit graph.
        
       | divbzero wrote:
       | The following tip from OP could be rather useful.
       | git rebase --exec 'make test' main
       | 
       | _The_ --exec  <command> _flag allows you to run any shell command
       | after each rebased commit, stopping if the shell command fails
       | (which is signaled by a non zero exit code)_.
        
       | OJFord wrote:
       | I don't know if it's possible to write an article like this and
       | not just be preaching to the choir; ignored by the flock that's
       | already decided it doesn't like it.
        
         | [deleted]
        
         | chris_wot wrote:
         | So what? If the crowd doesn't want to use it, what of it? You
         | only rebase on your own changes before you push the patches.
        
           | OJFord wrote:
           | Well my suggestion really was just that it's pointless to
           | write about, because you won't convert anyone. (Not '..and
           | you should be doing xyz because that will convert them and
           | that's what we want'.)
           | 
           | But to answer your actual question, there are various ways in
           | which what others on a team do affects you:
           | 
           | - CI building 'merge branch master' all the time _on master_
           | , because of merge-pulling upstream changes after committing
           | 
           | - spaghetti merge feature branches (that you might be
           | reviewing, working jointly on, or as below)
           | 
           | - git log, blame, etc.
        
       | holoduke wrote:
       | Rebasing is merging multiple commits to one commit right?
       | Basically you commit your small changes to your local master
       | branch and at some point you merge them to one commit and push
       | them to master repo?
        
         | dnsmichi wrote:
         | GitLab team member here.
         | 
         | You can use `git rebase` to perform the so-called "squash"
         | action, that squashes multiple commits at once.
         | 
         | For example, the latest commits in the branch look like this:
         | 
         | 123 WIP1
         | 
         | 456 WIP2
         | 
         | 789 WIP3
         | 
         | 012 FeatureA
         | 
         | WIP1,2,3 as commits should be merged into a single Git commit,
         | and be put on top of the FeatureA commit - so to speak, use the
         | FeatureA commit as a new base.
         | 
         | Git uses the rebase command to do exactly that - you'll perform
         | an interactive rebase onto FeatureA commit. The interactive
         | rebase allows you to define specific actions.
         | 
         | "pick" keeps the commit. In order to perform a squash of the
         | WIP1,2,3 commits, you'll keep the first WIP1 commit, and tell
         | Git to continuously squash the next commits WIP2 and WIP3. Each
         | operation is done at once.
         | 
         | pick 123 WIP1
         | 
         | squash 456 WIP2
         | 
         | squash 789 WIP3
         | 
         | pick 012 FeatureA
         | 
         | This results in a new history and commit - squashing changes
         | the commit sha checksum, with new content in the Git commit, as
         | well as a new base commit.
         | 
         | 567 Squashed
         | 
         | 012 FeatureA
         | 
         | "squash" in an interactive rebase keeps the individual commit
         | messages for each commit, and at the end, the editor for
         | commits allows you to edit the final messages. This can be
         | helpful to review the squash action, and for example amend or
         | abort it.
         | 
         | If you plan to not keep the individual commit messages, "fixup"
         | throws them away and can be used as alternative action.
         | 
         | "git rebase -i" has more options - you can also stop at a
         | specific commit, and amend it, e.g. when a "git add" was
         | missing a file earlier.
         | 
         | Note: Any change to a commit within the Git history forces all
         | later commits to change too, as the linked commit base changes
         | too, thus regenerating the sha checksum. This entirely rewrites
         | Git history trees, and can be very invasive - if you intend to
         | keep specific commit IDs (for release tags for example), ensure
         | that the workflows to not allow rebasing on certain branches.
         | One possible workflow is to keep the main default branch
         | protected, disallowing to rebase and push a changed history,
         | add git tags there, and only rebase in a Merge Requests branch
         | prior to review/approve/merge cycles.
         | 
         | Moving from Git commands to GitLab - GitLab also offers a Merge
         | Request option to squash commits automatically when the MR is
         | accepted, so that all commits in the MR branch are squashed,
         | and you don't need to do it manually.
         | https://docs.gitlab.com/ee/user/project/merge_requests/squas...
         | 
         | Last but not least - the quick action /rebase in a MR comment
         | allows to trigger a rebase via the UI too, thus not requiring
         | client side clone/fetch/rebase. More tips in
         | https://about.gitlab.com/blog/2021/02/18/improve-your-gitlab...
        
         | hkdobrev wrote:
         | That's squashing which could be achieved with rebasing, but
         | rebasing is larger than that which allows you to order and edit
         | your history.
        
         | shagie wrote:
         | Rebasing is re-applying a sequence of commits to a different
         | parent.
         | 
         | I like using explain git with D3 to show how things work -
         | https://onlywei.github.io/explain-git-with-d3/#rebase
         | 
         | Compare that with merge - https://onlywei.github.io/explain-
         | git-with-d3/#merge
         | 
         | At the end, the HEAD has the same content, but the structure of
         | the graph is different.
         | 
         | Note that rebase falls in the set of "rewriting history"
         | operations in git and so pay attention to the caveat in the
         | explanation:
         | 
         | > For this reason, you never want to rebase commits that have
         | already been shared with the team you are working with.
         | 
         | Rebase and reset are two of the commands that need to be done
         | with caution and full awareness if working with commits that
         | have been shared with other people.
        
       | Tade0 wrote:
       | No rebase tutorial is complete without the --onto option, which
       | lets you essentially transplant a series of commits to a
       | completely different branch.
       | 
       | Very useful when you've created a branch(A) based on another
       | branch(B), which in turn was based on master, but in the meantime
       | master had a few commits added, so while it's trivial to rebase B
       | with master, rebasing A with an updated B won't work.
        
         | b3morales wrote:
         | The latest git release has an option to handle this multiple
         | branch scenario for you: `git rebase --update-refs` I don't
         | know why I can't find any announcement of this other than a
         | GitHub blog, but here it is:
         | https://github.blog/2022-10-03-highlights-from-git-2-38/
        
       | perryizgr8 wrote:
       | Rules I would have everyone follow if I was a dictator:
       | 
       | 1. 1 PR, 1 commit.
       | 
       | 2. 1 PR cannot have more than 50 lines of product code added. Any
       | number of lines can be removed. You can have up to 100 lines of
       | test code.
       | 
       | 3. Every PR should include a set of tests for the added/changed
       | functionality. They must pass.
       | 
       | 4. Git merge is forbidden. Everyone must rebase.
       | 
       | 5. Every PR goes into master. Nobody can push to master. You can
       | create as many feature branches you like, but definition of done
       | is that your code is available on master.
       | 
       | 6. Identify relevant existing test cases and make sure they are
       | passing.
       | 
       | 7. Master must always be in a state that it can be deployed
       | instantly.
        
         | lamontcg wrote:
         | > 1 PR cannot have more than 50 lines of product code added.
         | Any number of lines can be removed. You can have up to 100
         | lines of test code.
         | 
         | Hard disagree.
         | 
         | Landing a single class/module to implement new functionality
         | may take more than 50 line of code and 100 lines of test, even
         | though conceptually the additional functionality is simple and
         | it amounts to mostly boilerplate and looks like every other
         | class that implements the pattern.
         | 
         | Some large plumbing refactorings or CI refactorings are
         | difficult to do in small chunks. I'm perfectly fine with a PR
         | that replaces one internal API with another one and then has
         | hundreds of small copypasta fixes littered around the codebase
         | to swap out the APIs. Anyone should be able to read that
         | without cognitive overload.
         | 
         | Tests are also commonly over 100 lines of code since they tend
         | to be repetitive by nature, and I'd like to not see those
         | artificially broken up into smaller PRs since the most
         | important question I've usually got is if all the cases are
         | covered or not. Breaking 300 lines of tests up into 3 different
         | PRs to satisfy some kind of line-length metric means now the
         | most important question I have needs looking at all 3
         | simultaneously and that is deeply counterproductive and totally
         | useless. And small code changes with lots of comprehensive
         | tests which fill out cross products of different API usages are
         | great and should be encouraged.
         | 
         | And while I don't personally like the dozens-of-tiny-atomic-
         | commits approach, I deeply don't care if other people do it or
         | not. I've never found it useful to read their PRs, or even
         | after the fact, but I won't stand in the way of them doing that
         | if it is what gives them enjoyment (OTOH, I never do that).
        
           | AtlasBarfed wrote:
           | Maybe a good rule for projects in maintenance mode. Large
           | scale refactors? Well, that's impossible under these rules,
           | well unless you go full LISP on what a line does.
        
             | lamontcg wrote:
             | Mostly what I've done is maintenance mode, that's where if
             | you try to touch something it is often very complicated in
             | secondary effects and fixes, and requires lots of tests.
             | And additions of functionality which are bolt-on will come
             | with 10 years of accumulated requirements around the shape
             | of any new code and the tests.
        
       | itslennysfault wrote:
       | A lot of people have hate for rebase, but I've always LOVED it.
       | I've always had way less issues with it than merge. Whenever I do
       | a feature I work in a feature branch then just rebase it with the
       | target branch (main) before submitting the PR and it is a really
       | painless workflow I've used for years.
        
         | rmetzler wrote:
         | I really try to like git rebase, especially git rebase -i and
         | at one time I even used a special tool to help with that. What
         | I find is that I see a lot more merge conflicts than in Gitlab
         | MRs, but it could also be that the tooling on my machine is
         | suboptimal: switching between VSCode as the editor and using
         | vim in a separate terminal for git. In vim I don't see the
         | current commit where the conflicts appear.
        
           | hoten wrote:
           | What was your tool? Was it more than the --fixup/--autosquash
           | feature (perhaps your tool predated that)?
        
         | BeFlatXIII wrote:
         | I made some minor contributions to MuseScore a few years ago
         | and they turned me on to the joy of rebasing.
        
       | ludwigvan wrote:
       | On Mac, I prefer Gitup, a free and open source GUI which makes
       | rebases (and a bunch of other git operations) much easier:
       | https://github.com/git-up/GitUp
        
       | DBCerigo wrote:
       | A much more in-depth, advanced, and more valuable imo, article on
       | the same topic https://medium.com/@porteneuve/getting-solid-at-
       | git-rebase-v...
        
       | kartoshechka wrote:
       | irony is that my team use gitlab and we have auto squash before
       | merge, avoiding manual rebasing
        
       | xyzzy4747 wrote:
       | I would recommend not doing anything complicated such as git
       | rebase and just add more commits, patches (git diff / apply), or
       | merges until your code works. If the number of commits is large,
       | it doesn't really matter. Optimizing for a pretty looking git
       | history is probably the most foolish thing to focus on.
       | 
       | If you are doing anything that involves rewriting the history you
       | are doing it wrong.
        
         | Nagyman wrote:
         | > Optimizing for a pretty looking git history is probably the
         | most foolish thing to focus on
         | 
         | It's not about "pretty"; commits are a form of _communication_.
         | Do we send emails without editing before hitting send? It's a
         | means to optimize for easier reviews through better
         | comprehension of the changes, which also leads to faster
         | reviews. Our colleagues don't want to read a bunch of
         | intermediate commits.
         | 
         | > If you are doing anything that involves rewriting the history
         | you are doing it wrong.
         | 
         | Care to elaborate? What's your general strategy?
        
           | chriswarbo wrote:
           | > It's not about "pretty"; commits are a form of
           | _communication_. Do we send emails without editing before
           | hitting send?
           | 
           | Writing clear, atomic commits is a good idea regardless of
           | whether you use rebase or not.
           | 
           | In your email analogy, rebasing would be altering previous
           | messages in the chain. That doesn't make rebasing look good!
           | 
           | > > If you are doing anything that involves rewriting the
           | history you are doing it wrong.
           | 
           | > Care to elaborate? What's your general strategy?
           | 
           | Not the parent, but to me the most important part of VCS
           | history is _accuracy_. Rebasing commits (or cherry-picking
           | them) changes their context; that context can be important
           | for understanding why things were done in a certain way. For
           | example, imagine we 're digging through the following
           | history, to understand how some feature 'bar' works:
           | * Add workaround for Error(foo) in feature bar       |
           | * Implement feature bar       |       * Bump dependency baz
           | to eliminate Error(foo)
           | 
           | Why was a workaround for Error(foo) added, if that error had
           | already been eliminated? Did that dependency change not work?
           | Is there some more permanent way to eliminate Error(foo)? Is
           | the workaround still needed?
           | 
           | Compare that to the following, more accurate history:
           | * Merge       |\       | * Add workaround for Error(foo) in
           | feature bar       | |       | * Implement feature bar       *
           | | Bump dependency baz to eliminate Error(foo)       | /
           | |/
           | 
           | Here it's much clearer what's going on: the dependency change
           | was not in place when that workaround was added. Hence the
           | workaround shouldn't be needed anymore. Rebasing the 'feature
           | bar' changes on to the 'dependency baz' changes throws away
           | that information.
        
         | k_ wrote:
         | Good luck bisecting such a repository, unless you squash PRs
         | (for which build passes of course)
        
           | WorldMaker wrote:
           | git bisect --first-parent bisects only the straight line of
           | first parents of merge commits. If you --no-ff PRs and always
           | have merge commits, it is essentially a bisect at the PR
           | level without any need to squash the graph.
        
       | bob1029 wrote:
       | Rebase is something that I see a lot of developers shy away from
       | but it is usually the right way to get a feature branch re-
       | aligned.
       | 
       | My practice is to rebase all my pending PRs each morning to make
       | sure that the prior day's activity is coalesced.
       | 
       | If you wait weeks and weeks to do the first rebase for a big
       | change set, you can wind up visiting the same files and conflicts
       | _way_ more times than is logical. In my experience, this results
       | in a much greater chance of screwing something up along the way,
       | further reinforcing for some developers that the rebase is bad.
       | 
       |  _Timely_ rebase is the answer.
        
       | hoten wrote:
       | --fixup has been incredibly useful for my rebase workflows.
        
       | manbash wrote:
       | Anyone who has experienced rebasing a PR on github knows how much
       | it hurts the review process.
        
       ___________________________________________________________________
       (page generated 2022-10-06 23:02 UTC)