[HN Gopher] Minimum Viable Git for Trunk-Based Development
       ___________________________________________________________________
        
       Minimum Viable Git for Trunk-Based Development
        
       Author : elischleifer
       Score  : 44 points
       Date   : 2022-11-30 15:42 UTC (7 hours ago)
        
 (HTM) web link (blog.trunk.io)
 (TXT) w3m dump (blog.trunk.io)
        
       | bsima wrote:
       | How does this guy run a developer tools company called "trunk"
       | and yet doesn't understand rebase? Talk about killing
       | credibility...
        
         | tkiolp4 wrote:
         | Trunk development is not about rebase, it's about short-lived
         | branches that get incorporated into the main branch soon. How
         | they get incorporated (git merge is good enough) is not
         | relevant.
        
       | LocalPCGuy wrote:
       | I personally am a proponent of rebase, but not all the time and
       | not for every workflow. It has it's place though, IMO. I
       | like/value clean history and good commit messages (although I
       | admit I don't always succeeding providing that all of the time).
       | I prefer to stage my commit pieces at the hunk level at the
       | largest. I like to rebase my branches before merging them into
       | release or main (depending on git strategy as a whole), but it
       | isn't always necessary. I use interactive rebase from time to
       | time to clean up my feature branches (especially longer running
       | ones). This is all stuff I prefer in my own workflow.
       | 
       | That said, every time I try to really teach someone rebase,
       | particularly a new dev, I understand why people shy away from it.
       | I did for a very long time. So I totally understand and get why
       | the above style workflow may terrify folks (or just seem
       | unnecessary). It is easy to mess up and there are a lot of little
       | gotchas if someone isn't careful. And worst of all, it can result
       | in lost work (although even that is "usually" recoverable, but
       | not always). I do think there are some benefits to it, and I
       | think it is something that can be integrated into a dev's
       | workflow a bit at a time. And it really doesn't take
       | significantly more time, in my experience.
       | 
       | I'm not gonna argue here for adopting that. Except for "no commit
       | messages", I'd be pretty ok with a workflow as outlined by this
       | post. I do think folks should understand how rebase works, what
       | commits will be moved/changed when they run a rebase (this is
       | vital), and how to recover when a rebase goes bad (no, not
       | reclone, not generally even delete branch and check it out
       | again).
       | 
       | .
       | 
       | Couple random thoughts I try to communicate to folks who decide
       | to utilize rebase more in their workflow:
       | 
       | - rebase often (if main updates often)
       | 
       | - if worried the rebase may be messy, create a temporary branch
       | prior to starting the rebase at the feature branch HEAD - allows
       | for an easy way back (and prevents lost code)
       | 
       | - don't rebase shared branches - this is a tool to use PRIOR to
       | "sharing" (i.e. pushing) code
       | 
       | - squash/clean up unneeded commits before rebasing on another
       | branch (this may bring it all the way down to a single commit,
       | but for larger features, I think there is value in seeing the
       | main decision points along the way)
       | 
       | - fix conflicts with the code at the specific commit you are on
       | only, don't fix it with the eventual end result X commits down
       | the line - this will generally avoid the dreaded "fix the same
       | conflict over and over for each commit" problem some people
       | encounter with rebasing
       | 
       | - remember rebase creates new history - it doesn't rewrite
       | history (however, old commits will eventually be garbage
       | collected)
       | 
       | - pro tip: understand how `rebase --onto` works, sometimes you
       | shouldn't, or at least don't want to, take all of the commits
        
       | sossunday wrote:
       | > git push origin
       | 
       | > Push my code to the remote; likely spinning up lots of machines
       | in CI to check my work.
       | 
       | That's a good callout; something that I have noticed I frequently
       | miss when iterating on my code is the cost of the CI/CD systems
       | already set up. It's something to consider especially when
       | iterating using a system like Sapling for Stacked PRs; each
       | individual PR push may update a chain which causes a lot of
       | wasted CI/CD time.
        
         | dapirian wrote:
         | Especially if you're using a finite pool of CI runners. Lots of
         | companies do run their own CI runners either for added
         | security, or to get persistent CI machines with a hot local
         | cache so builds/tests are much faster. Then everyone's PRs are
         | blocked waiting for CI machines just because of people's weird
         | push workflows or micro stacked PRs
        
         | mdaniel wrote:
         | I feel that a lot of my colleagues use "git push" as a backup
         | mechanism, but GitLab actually supports that workflow via `git
         | push -o ci.skip` to distinguish between "yes, just back up my
         | commits" versus "ok, I'm really ready to test them". I'm aware
         | of the commit-message hack used by other CI systems, but I much
         | prefer that out-of-band mechanic
         | 
         | They have a ton of other handy toys, even if the syntax is ...
         | Very Git :-(
         | https://docs.gitlab.com/ee/user/project/push_options.html#pu...
         | I suggested a feature-request to add `git push -o gitlab.help`:
         | https://gitlab.com/gitlab-org/gitlab/-/issues/359267 as well as
         | showing the CLI equivalent for the web workflow:
         | 
         | CI variables: https://gitlab.com/gitlab-
         | org/gitlab/-/issues/359268
         | 
         | MR: https://gitlab.com/gitlab-org/gitlab/-/issues/359269
        
       | jangofett27 wrote:
       | I'll always be a rebase diehard, but the core message here is
       | great. If you have to do more than a little bit of git surgery,
       | you're probably doing something else wrong.
        
         | aleyva wrote:
         | yep, well summarized!
        
       | alkonaut wrote:
       | Without rebasing, tools for managing PRs might show the merged
       | mainline commits in the PR.
       | 
       | Some times they are described as such "merged master into
       | feature" and can be avoided if you review the PR _per commit_.
       | But more often I want to review the PR as a whole, and then the
       | tool fails to show a good diff of what's actually developed in
       | the PR. This to me is a _much_ larger problem than the log
       | pollution, which can be solved by squashing.
       | 
       | Other than that (missing the bigger reason for rebase and
       | focusing on a lesser argument in my opinion) I quite agree with
       | the article.
        
       | jbergknoff wrote:
       | > The easiest practice to implement for peak Git efficiency is to
       | stick to a subset of commands
       | 
       | This has been my experience as well.
       | 
       | Great article, thanks! I've been using essentially this same
       | subset of commands for many years, and it's worked extremely well
       | for me: does everything I need/my team needs, and avoids
       | complication. I'm glad to have this as a reference I can point
       | people to when they ask for git advice.
        
       | federicoweber wrote:
       | I'm a huge fan of squash rebase, myself. really it's my default,
       | and I find it particularly useful for long run branches.
        
       | gabrielgio wrote:
       | > you need to re-clone from scratch -- even if you did nothing
       | wrong.
       | 
       | I don't think you will need to reclone if did nothing wrong. You
       | can always use `git reset --hard origin/...`, and if that does
       | not work the you definitely did something wrong.
       | 
       | > But in Linus's own words, Git is "the information manager from
       | hell."
       | 
       | That git is not the same git we have today, and it was handed
       | over to another person quite early in the development. Although I
       | agree that git ux is sometimes confusing.
       | 
       | > Limit your Git actions ... for peak Git efficiency
       | 
       | I pretty much disagree, if I can give my two cents, read the
       | manual. Git have some really handy tooling that can help with
       | non-git issue (e.g.: `git bisect`). Limiting your knowledge
       | brings no benefit.
       | 
       | I like some point of the text, but overall I don't like the
       | premise. it exaggerate a lot a problem to prove a point.
        
       | itslennysfault wrote:
       | I finally understand why some people are so against rebase.
       | They're doing it wrong.
       | 
       | I've always heard people talk about how it doesn't scale, but I
       | use rebase like 99% of the time, and have worked on projects with
       | hundreds of ICs. This is the first time I've seen someone explain
       | it in a way where I get it. NO I'M NOT FORCE PUSHING TO MAIN YOU
       | SILLY NILLY! Turns out I'm "squash rebasing." I guess I didn't
       | know I need to specify that.
       | 
       | I do it slightly differently tough. I use git commit --amend to
       | build up a single commit as I go.                   git checkout
       | -b blah-feature              # do some work              git
       | commit -m "Main description of my feature"              # do more
       | work              # no -m, and then I just add bullet points for
       | each subsequent change in vim (example below)         git commit
       | --amend
       | 
       | Then, once I'm ready to make a PR I do the following:
       | # pulls from remote without merging         git fetch origin main
       | # adds my single commit to the end of the current main
       | git rebase main              # push up feature branch for code
       | review         git push              # get yelled at about --set-
       | upstream, and copy/paste that command :-)
       | 
       | My commit messages typically look like:                   Add
       | some new feature              - do some sub task         - do
       | another sub task         - ...
        
         | LocalPCGuy wrote:
         | I don't agree that folks who rebase multi-commit branches are
         | "doing it wrong". Even if there are multiple stops along the
         | way, that should not be considered a bad thing if it's
         | understood what it is doing.
         | 
         | The way I look at it, lets say I have 10 commits. If I rebase
         | main, commits 3, 4, 7, 10 have "conflicts" with the code that
         | is on main now compared to when I started writing my feature
         | branch and making commits. But, now, I have an opportunity to
         | update code in each of those commits as if I was writing it
         | based on what is now currently on main. If done like that,
         | incrementally, it usually doesn't cascade into conflicts on
         | each commit.
         | 
         | The problem, IMO, comes when at commit 3, the dev says "Oh, I
         | did this like this in commit 10, so let me just put that
         | solution here in commit 3 to resolve this merge conflict". Now,
         | instead of 4 conflicts, you have conflicts on all of the
         | commits between 3 and 10 (because the dev in effect moved the
         | fix from 10 up 7 commits from where it originally was
         | committed). Instead, each conflict resolution should aim to
         | maintain the code as close to the committed code as possible
         | while integrating the code from main. That way also, the
         | feature branch commits still reflect the iterative process that
         | having multiple commits is designed to show.
         | 
         | I don't embrace a FULL squash rebase, but I do embrace cleaning
         | up your branch commits with an interactive cleanup rebase (not
         | on main, just going through the commits for the branch and
         | squashing any minor fixes that belong with the previous commit,
         | etc.) THEN, once you have a clean feature branch, rebase main.
         | The feature branch may now have, instead of the 10 commits
         | above, eliminated 6 commits that were just things like minor
         | test fixes, typos, etc, and now only has 4 commits total.
         | Instead of 4 conflicting commits, it may now only have 1 or 2,
         | making the rebase simpler as well. And the branch still
         | maintains the traceable history of the development of that
         | feature (assuming good commit messages were used, which is not
         | something the original poster values either).
        
         | bheadmaster wrote:
         | > I use git commit --amend to build up a single commit as I go.
         | 
         | While this is a sensible approach, it doesn't work in scenarios
         | where you essentially have to "test in production" to actually
         | test things (Jenkins, looking at you). I've experienced some of
         | that in the real world, and combined with the inability to
         | force-push, it seems like the squash rebasing is the most
         | sensible thing to do to keep main clean within these
         | constraints.
        
         | scelerat wrote:
         | Many times have I seen a green developer throw up their hands
         | at a rebase attempt, after which we learn they were doing this:
         | git checkout master; git pull              git checkout -b fb
         | git commit              git commit              # new changes
         | arrive on master branch                  git checkout master;
         | git pull;               git checkout fb; git merge master
         | git commit              # "went to the git brownbag and heard
         | about rebase for the first time,               # missing that
         | part up front about not intermingling merges with rebases
         | # and not having a good mental model of git              git
         | rebase master              # WTF conflict everywhere! rebase
         | sucks
        
           | tkiolp4 wrote:
           | The flow you have described works (besides the last 'git
           | rebase master'), though. When 'git merge master' is run, the
           | developer either get conflicts (which can be then fixed) or
           | not. After that 'git push' and you can open a PR. I certainly
           | don't see anything wrong with that flow.
        
         | tkiolp4 wrote:
         | Why not just 'git merge main' instead of 'git rebase main'?
        
           | LocalPCGuy wrote:
           | Because they do different things. It's right there in his
           | post:
           | 
           | > # adds my single commit to the end of the current main
           | 
           | The biggest benefit to this IMO is that you can resolve
           | conflicts in YOUR branch, get it all cleaned up, and then
           | when you merge there are no conflicts. This allows you to
           | test any changes made during conflict resolution in your
           | feature branch still.
        
         | knff wrote:
         | Slightly off topic
         | 
         | > get yelled at about --set-upstream, and copy/paste that
         | command :-)
         | 
         | But you might like this https://git-scm.com/docs/git-
         | config#Documentation/git-config...
        
           | JamesSwift wrote:
           | I just added an alias                 alias gpush='git push
           | --set-upstream origin $( git branch --show-current )'
        
         | patmcc wrote:
         | Yah, I don't think anyone minds those kind of rebases. It's
         | when they're done on shared branches like master that they're
         | _incredibly_ messy and dangerous.
        
           | itslennysfault wrote:
           | That totally makes sense. I never really dug in. Mostly I'd
           | tell people I always rebase in passing and get a glare or
           | snarky comment, but never bothered to argue about it because
           | it works for me and never caused issues.
        
       | surf_wreck21 wrote:
       | I agree; maybe when git was new and actually being used in a
       | decentralized fashion some of the more advanced operations were
       | necessary. But with the typical checkout/branch/PR/merge flow
       | from GitHub and others, I rarely need anything but git merge
       | (with squash merging when merging a pr)
        
       | dboreham wrote:
       | > git add -A .
       | 
       | > Add everything I'm working on (new and edited files).
       | 
       | Bad idea. Extraneous cruft that isn't caught by .gitignore will
       | leak into the repo. Always run git diff and git status first to
       | see what you are about to add.
        
         | elischleifer wrote:
         | I hear you. But nothing goes directly into main. The working
         | branch is not sacrosanct you know what I mean? I'd rather clean
         | up anything that leaks in before merging and a good .gitignore
         | can protect against most noise.
        
           | TrickyRick wrote:
           | Sure but it goes in the repo. Forgot to add .env to the
           | .gitignore? You probably just committed a secret. Sure you
           | can force push to get rid of it but if you're using Github
           | it's still saved so it needs to be rotated now.
        
             | alkonaut wrote:
             | What's "the repo" here? What I commit goes into my copy of
             | the repo. Only what I push goes into any repo anyone else
             | sees. Before pushing I always go through what's in the
             | branch and clean up/rebase etc. Sure it's easier to
             | accidentally push a file you shouldn't have if you have
             | added it locally but _committing_ alone doesn't necessarily
             | mean you need to rotate a secret.
        
               | LocalPCGuy wrote:
               | That is a case where (as you note) you'd need to do some
               | sort of destructive fix to eliminate the file from your
               | local repo. Whether it's a rebase or something else, a
               | person then needs to know "the advanced parts" that the
               | blog post is advocating aren't really needed if "git is
               | done correctly". Better to just not commit files/hunks
               | accidentally in the first place - I know, it's not a
               | perfect world, yada yada - just trying to provide the
               | counter point to the counter point.
        
               | alkonaut wrote:
               | Yeah I'd say interactive rebase and soft resets is part
               | of my "limited toolbox" for git that I wouldn't go
               | without. (I don't stage hunks, don't merge in either
               | direction etc, so I leave some other parts of the larger
               | toolbox alone).
        
           | simplotek wrote:
           | > But nothing goes directly into main.
           | 
           | That's not a reasonable argument. The problem is pushing
           | confidential info into a repository. It matters nothing what
           | the branch you push it is called.
        
             | elischleifer wrote:
             | FWIW - we run secret detection in our trunk check precommit
             | action - so we make sure that secrets are never committed
             | into local or remote branches.
        
         | denimnerd42 wrote:
         | nah, I always git add --all && git commit -m "issu-12 my short
         | message"
         | 
         | if something leaks and I need to add to gitignore I'll amend.
         | 
         | there's definitely cases for staging more complicated edits but
         | not in my daily work.
        
         | Forge36 wrote:
         | combined with the authors disdain of commit messages or
         | documentation I can't figure out where they've chosen to
         | document why changes are made.
        
           | nimbus3001 wrote:
           | commit messages != documentation
        
       | scelerat wrote:
       | This guy doesn't understand rebase. Rebase is an organizational
       | tool. it's housekeeping for keeping your commits clean. One
       | reason to learn how to do rebase is so that your feature branch
       | is tidy so when you merge it to main, main itself is tidy.
       | Another is that as you perform the exercise of cleaning up your
       | commits you are performing code review, something that, up until
       | this point, you've just been throwing at your co-worker without
       | much thought as soon as all the tests pass.
       | 
       | "But my feature branch gets squashed anyway"
       | 
       | 1. I believe that in itself is a mistake, especially as feature
       | branches get large and, though you say you're all for small
       | feature branches, your commit history says you do something
       | different.
       | 
       | 2. You don't clean up that giant merge commit message with all
       | those "WIP" "fixed stupid mistake" comments in there.
       | 
       | Use rebase to keep your workspace clean and main/master
       | comprehensible to your colleagues.
        
         | mooreds wrote:
         | Here's my favorite rebase presentation. He really emphasizes
         | keeping history clean.
         | 
         | https://www.youtube.com/watch?v=UWwazJ_46s0
        
       | GMoromisato wrote:
       | Nice! Maybe someone should create an opinionated git front-end to
       | enforce some of these patterns on a team.
       | 
       | The irony, IMO, is that Linus prefers C to C++ exactly because
       | C++ gives developers too much rope.
        
       | everybodyknows wrote:
       | Clicking through a self-link in the article
       | https://blog.trunk.io/git-commit-messages-are-useless-c2f3c4...
       | we read:
       | 
       | > This isn't grade school, you don't have to show your work As
       | you become an efficient engineer, the path you took to get to the
       | final state of a pull request becomes far less important -- and
       | is academically interesting at best. You shouldn't have to show
       | your work like you did in school. Land the feature or bug and
       | move on to the next one. The code speaks for itself (alongside
       | some judiciously placed comments).
       | 
       | > Having granular annotations of all your work is unnecessary,
       | ...
       | 
       | This premise underlies the particular workflow that the posted
       | article assumes, and all the described command+option
       | incantations are directed to it.
       | 
       | But there is another, very different git workflow used by a
       | project we've all heard of, and that is the Linux kernel core
       | code. The trunk.io workflow is unsuitable for Linux due to
       | different requirements. Some of which being:
       | 
       | 1. Commitment to support for indefinite future.
       | 
       | 2. Large, complex feature PRs.
       | 
       | 3. Human review of PRs, by maintainers fully empowered to reject.
       | 
       | 4. A low-level programming language, in which subtle bugs are
       | easily introduced.
       | 
       | Also different luxuries:
       | 
       | 1. Willingness to put off merge of a "hot" new feature
       | indefinitely.
       | 
       | So, kernel PRs are structured as a linear series of numbered
       | patches meeting the requirement that each step along the way
       | compile cleanly. This is primarily to ease the task of the
       | maintainer responsible for the subsystem involved, and who will
       | have deal with the fallout of bugs introduced by the PR. Example:
       | 
       | https://lore.kernel.org/rcu/
       | 
       | Credential: I have written code for the Linux kernel core, and it
       | was merged, and it was buggy.
        
       ___________________________________________________________________
       (page generated 2022-11-30 23:02 UTC)