[HN Gopher] Use Git tactically
       ___________________________________________________________________
        
       Use Git tactically
        
       Author : aloisdg
       Score  : 94 points
       Date   : 2022-04-07 12:20 UTC (10 hours ago)
        
 (HTM) web link (stackoverflow.blog)
 (TXT) w3m dump (stackoverflow.blog)
        
       | obelos wrote:
       | Why no squash? It's a private dev branch, so it doesn't throw off
       | anyone else's work. Just commit to your heart's content for every
       | little experiment. Write trivial commit messages like
       | "checkpoint" because `git show` will contain so little code it's
       | easy to figure out what's what. If you later decide you've headed
       | down the wrong path, `git checkout -b my_feature_take2 HEAD~n`
       | and start back up from a known point. When you have a functional
       | final result, `git rebase -i master` to squash and groom the
       | commits into more meaningful aggregations. Or just a single
       | commit, if it makes sense for the context.
       | 
       | Interactive rebasing with fixup/squash makes the end result very
       | readable. `git reset` and `git add -p` can also be a huge boon
       | when tidying up a branch before PR.
        
         | bentcorner wrote:
         | The author's reasoning behind not squashing:
         | https://blog.ploeh.dk/2020/10/05/fortunately-i-dont-squash-m...
         | 
         | I can understand they don't want to oversquash - I rebase &
         | squash so that each commit should be able to stand on its own.
         | I think the above link is a good argument _for_ squashing (and
         | rebasing) to the point that each commit should leave the system
         | in a state where everything works, because otherwise you can 't
         | use `git bisect` and actually determine if it's good or bad. I
         | will often have more granular commits where I break something
         | and then fix it in the next commit.
        
       | jstimpfle wrote:
       | So editing code is like free climbing now? My IDE has infinite
       | undo, and some editors (like vim) can go back to arbitrary points
       | in time. The relatively unlikely case that the editor crashes (or
       | I accidentally shut it down) and I lose a little bit of undo
       | state (or a few lines of code) is just not worth it in my
       | opinion.
       | 
       | I commit maybe once every few hours. I don't recall my diff
       | exceeding 2000 lines, normally it's a few 100s. I can't recall
       | the last time I lost code. It only happened a few times ever. It
       | was never a problem to quickly redo those changes (and possibly
       | improve along the way).
       | 
       | Is there any other point in doing micro-commits other than being
       | "safe"? If not, I have other things to worry about.
       | 
       | Besides, my editing environments don't play well with checking
       | out an older commit to see what's there - they don't recognize
       | this as "going back". Much better to simply undo.
        
         | FractalHQ wrote:
         | When I was less experienced, my code was more error-prone and
         | micro-commits saved me often. Either way, VSCode won't lose
         | your progress regardless of how it quits. It will always drop
         | my undo history on restarts though (which can be a real pain if
         | I'm exploring and haven't made a commit in hours).
        
       | catchmeifyoucan wrote:
       | Just my opinion. I'm still looking for a better editor with
       | "auto-save" commits, or maybe a VSCode plugin. It should just
       | wrap around my build command (or let me pass something), and if
       | it builds, it should do this in the background as a snapshot. I
       | think defining a good build in the context of runtime behavior is
       | hard. I don't necessarily need all of the intermediate states it
       | in git, though I don't mind if this tool uses git to power the
       | snapshots. Maybe there's a world where version control is
       | abstracted
        
         | AlphaSite wrote:
         | IntelliJ keeps a running history of all the files on your
         | system so you can always go and show history on a file or
         | directory and see what you've done (in addition to git etc).
        
           | awelxtr wrote:
           | Eclipse too iirc
        
         | kmarc wrote:
         | Vim's non-linear undo[1] history is hard to beat. Set undofile
         | [2] and you are done with local versioning. For visualisation
         | of the undo tree, install undotree [3]
         | 
         | [1] https://vimhelp.org/undo.txt.html#undo
         | 
         | [2] https://vimhelp.org/options.txt.html#%27undofile%27
         | 
         | [3] https://github.com/mbbill/undotree
        
       | cranekam wrote:
       | > Free-climbing it is an incredible endeavor [..] Honnold didn't
       | just free-climb El Capitan [..] Or, that's true for the free
       | climb
       | 
       | Minor terminology pedantry: _free climbing_ merely means making
       | progress using only one 's hands and feet (or other body parts as
       | appropriate) on the rock. It is in contrast to other styles
       | including _aid climbing_ , where it's totally fine to do
       | something like place an expanding cam in a crack and step into a
       | sling attached to it, thus using the equipment to make progress.
       | You can still place cams and other stuff when free climbing but
       | they're just there to save you if you fall. It's not free
       | climbing if you're using gear to get up the wall.
       | 
       | Free solo climbing is free climbing without any protective
       | equipment. If you fall, you keep falling until something else
       | arrests you (the ground, a ledge, etc).
       | 
       | Honnold practiced freeing all the moves with protection until he
       | was confident he could solo the route.
       | 
       | It's common to refer to free soloing as "free climbing" but it's
       | not the same thing. Though people who aren't climbers likely
       | don't care about the difference anyway, and that's fine. I'm just
       | pointing it out in case anyone here is interested.
        
         | dguest wrote:
         | If we're going to get into it, coding with git makes you more
         | of a trad climber and _less_ like a free soloist. Sometimes you
         | run it out when the going is easy, sometimes you put in some
         | extra protection when it looks sketchy. It 's all about knowing
         | your limits and taking calculated risks.
         | 
         | No one ever forces you to pull out all your gear and free solo
         | the route, just like no one is going to delete your git repo
         | and ask you to rewrite your code from scratch. These are just
         | things a tiny minority of people do, sometimes with disastrous
         | results.
         | 
         | That said I like the analogy. But maybe the take home is that
         | we don't all need to be Alex Honnold, where one mistake means
         | certain death, and can instead settle to be the guy who takes
         | the occasional 15 foot fall.
        
       | ktpsns wrote:
       | Many (mediocre) programmers see/use git only as a tool for
       | sharing code with collaborators. These people can be easily
       | identified by leaving traces of meaningless commit messages.
       | 
       | The key is to convince these people that the git history can be
       | very worthful if edits are commented appropriately. Rapid
       | committing in small steps comes after.
        
         | lalwanivikas wrote:
         | I feel attacked.
         | 
         | Jokes aside, what advice would you give to such developers?
         | Asking for a friend.
        
           | acemarke wrote:
           | I'm a _very_ big believer in maintaining an informative Git
           | history. I have some suggestions for practical Git usage
           | patterns in a blog post I wrote last year:
           | 
           | https://blog.isquaredsoftware.com/2021/01/coding-career-
           | git-...
           | 
           | TL/DR for that section:
           | 
           | - Write Good Commit Messages
           | 
           | - Make Small, Focused Commits
           | 
           | - Clean Up Commit History Before Pushing
           | 
           | - Only Rewrite Unpushed History
           | 
           | - Keep Feature Branches Short-Lived
           | 
           | followed by some thoughts on "Git Archeology" as a useful
           | concept.
        
       | keithnz wrote:
       | having mucked around with this in the past, in my experience, it
       | actually isn't very useful and you almost never need any of the
       | micro commits.
       | 
       | I use Jetbrains tools and it actually does this automatically
       | through local history. I've never really needed it, but if you
       | like that kind of thing, I'd suggest finding a tool that does it
       | automatically for you
        
       | oxff wrote:
       | Git has abhorrent user interface / experience, thank God some
       | people with fine taste in design made Magit, only way I can keep
       | my sanity if I have to use Git.
        
         | eternityforest wrote:
         | Git is trivial to use if you don't try to actually understand
         | it, follow the rules, and do stuff through a GUI.
         | 
         | If you have something more advanced than that, there's a bit of
         | essential complexity there that's kind of hard to get rid of
         | anyway.
         | 
         | There might be some better VCS out there, but I'd only want to
         | switch if everyone else does. Having to stay familiar with 2
         | different systems sounds worse than 1 mediocre one.
        
           | RealityVoid wrote:
           | Out of all the VCS systems I used, Git was the best. I used
           | and (meh) and a bunch of horrendous stuff (mks, Serena, a
           | couple more that I am trying to forget). So, of course, I'm
           | weary of trying out new things. Got world and I grokk it and
           | it is well suited for my messy mind.
        
       | uhuhoo wrote:
       | I do the opposite. Because VSCode helpfully highlights the bits
       | that were changed, I don't want to lose this indicator because of
       | a commit, so I often postpone commits until I am ready to move to
       | another part of feature. Then I use 'git add -p' to make multiple
       | smaller commits, and finally push to remote origin. I don't treat
       | commits as safelines, instead I try to make them logical
       | explanations of the reasons for the changed code.
       | 
       | My safeguard is "undo", but I rarely need it. If I do, I just
       | copy the contents of the file to a new one (ctrl n, ctrl a, ctrl
       | c, ctrl tab, ctrl v) before undoing the wrong path - because any
       | change on older version will break redo history, unfortunately.
        
       | seumars wrote:
       | I think micro-commits would make me overthink my commit messages
       | even more. I'd love to keep snapshots of my code in different
       | stages, but without having to put a label on X part of Y feature
       | at Z stage.
        
       | agumonkey wrote:
       | Then you have the people who script to scan,process the source
       | tree (stats, debug, else) to increase leverage. I wish I had this
       | talent naturally.
        
       | tomasreimers wrote:
       | ++ to this, beyond committing frequently for your own sanity,
       | doing so in a way that:                 1. Runs CI       2. Can
       | be merged independently (to reduce the chance of merge conflicts
       | by preventing drift from master/main)       3. Can be reviewed in
       | isolation (so your reviewers can follow your route)
       | 
       | Is also good. That's the idea of Stacked Commits
       | (https://graphite.dev/blog/post/N8SOs49y4bYdV1Vjf5qE).
        
       | davedx wrote:
       | > How you can use micro-commits to effectively apply the
       | Strangler Fig pattern.
       | 
       | Definitely a late April Fool's blog
        
       | jakeva wrote:
       | I'm irrationally annoyed that the first graphic misspells "stash"
       | twice.
        
       | Noumenon72 wrote:
       | If I'm about to embark on something where PyCharm's local history
       | isn't enough but I don't have an atomic commit ready, I just use
       | PyCharm's Save to Shelf action. Same as a stash but I mapped it
       | to Ctrl+S when I'm in the commit window. 90% of the time I don't
       | screw it up anyway.
        
       | kakuri wrote:
       | Staging can be a helpful alternative to micro commits. I'll write
       | some code, make some progress, revise, and once I get a small
       | changeset that I'm happy with I stage it. Then I'm free to make a
       | bunch of exploratory changes and the diff will show only those
       | changes, and I can back them out easily. I move forward bit by
       | bit like this until the feature is done then commit.
        
       | staindk wrote:
       | Something I kind of depend on--which may be a crutch, I'm not
       | entirely sure--is VS Code's "gutter indicators" feature[1] that
       | simply indicates where code was added/edited/deleted. It helps me
       | jump between changes to tweak further or undo them. The normal
       | diff view in VS Code is often useful too, and is essentially also
       | made less useful if you commit too frequently.
       | 
       | In the past this has caused me to commit way too little (i.e.
       | sometimes weeks between commits...), but I've improved on that
       | somewhat.
       | 
       | I still have a bunch of tabs open on my laptop about some Git
       | workflows that should allow me to commit more frequently and then
       | revert back to my 'starting point' for the gutter indicators and
       | other diffing. Must get around to trying some of that stuff out.
       | 
       | I'm probably missing some other useful tool or way of working to
       | help with this kind of thing - let me know if anyone else has
       | thoughts on this. Personally I don't think I could ever get to
       | this 'micro-committing' state, but there is a middle ground
       | somewhere that I'm aiming towards.
       | 
       | [1]
       | https://code.visualstudio.com/Docs/editor/versioncontrol#_gu...
        
         | hackabo wrote:
        
       | [deleted]
        
       | xt00 wrote:
       | One way to help this is to use some sort of tag text at the
       | beginning of the commit info that is useful so you can see this
       | in the sequence of commits that all go together (top is most
       | recent commit):
       | 
       | sql_parser: add new languages now supported by parse_unicode()
       | 
       | sql_parser: switch from using old parse_text() to parse_unicode()
       | 
       | sql_parser: add parse_unicode()
       | 
       | sql_server_health: ....
       | 
       | sql_server_health: ....
       | 
       | ...
       | 
       | rather than like:
       | 
       | fix stuff in this random function
       | 
       | updating functions using random function
       | 
       | The ones with the tags help the reader determine what things go
       | together much more easily, so even those lame commits are much
       | more helpful if they have a tag:
       | 
       | sql_parser: fix stuff in this random function
       | 
       | sql_parser: updating functions using random function
        
         | DogLover_ wrote:
         | Its called conventional commits
         | https://www.conventionalcommits.org/
        
           | xt00 wrote:
           | Yea the structure matches what you said but not really using
           | the set of words called out in that example like "feat"
           | "chore" etc.. Personally I find that less useful than
           | categorized tags that the developers just choose as they go
           | along and are meant as a thing to help you read the commit,
           | not to actually fit into a perfect index of possible tags
           | that are controlled someplace. Here's an example of the
           | categorization scheme in use (plenty of other examples out
           | there).
           | https://gitlab.freedesktop.org/mesa/mesa/-/commits/main
        
             | sicariusnoctis wrote:
             | I prefix with the "project/directory name" for [my
             | dotfiles](https://github.com/YodaEmbedding/dotfiles), e.g.
             | nvim:, zsh:, tmux:, i3:.
             | 
             | Nearly everything is a feat or fix, but it's much more
             | useful to know which project it applies to.
        
       | DogLover_ wrote:
       | This best practice of committing often never made much sense to
       | me. I find it typical that we as developers come up with such
       | practices that start to control how we work instead of us
       | focusing on getting work done. This practice makes even less
       | sense when we make PRs that once merged are squashed into one
       | commit?!
       | 
       | I try to make my commit history nice but the way people obsess
       | about it, I don't think is productive.
        
         | novocantico wrote:
         | I find that having one commit per logically-grouped set of
         | changes really helps me to focus on those changes and not get
         | distracted. Before I got into that habit, for _years_ I would
         | try to cram so many features in at once, and would have a
         | really hard time keeping track of each of their progress and
         | what 's left to be done for each, because I tried to do them
         | simultaneously. No more.
        
         | Nagyman wrote:
         | > This practice makes even less sense when we make PRs that
         | once merged are squashed into one commit
         | 
         | Up until the point of merging, other developers reviewing the
         | PR can see your development path, and optionally examine
         | individual commits. In GitHub at least, these individual
         | commits usually make their way into the squashed commit's
         | comments as a bulleted list of changes (after some cleanup),
         | which encourages better final commit messages in general.
        
           | DogLover_ wrote:
           | Rarely do I see people examine individual commits, perhaps
           | because it is already established that PRs should small and
           | branches short living.
           | 
           | The point about bulled list of changes is a good one.
        
             | saila wrote:
             | I examine commits regularly, sometimes going way back in
             | time. Maybe not daily, but pretty frequently. Usually, I'm
             | trying to figure out _why_ something is the way it is (so I
             | know if it can be changed, removed, or whatever), and a
             | clean history makes this exponentially easier.
        
         | squeaky-clean wrote:
         | I work in a way similar to the author, treating my micro
         | commits like a videogame quick save. But many videogames
         | separate "quick save" and "real save" in the UI and so do I.
         | 
         | I have a local branch, usually just called "wip" for work-in-
         | progress and commit to it frequently. Then when I want to push
         | to origin I pull all the contents from that branch into my
         | "real branch" and commit it as one commit. Then delete the wip
         | branch and repeat.
         | 
         | If I'm working on multiple tasks at once as my distracted brain
         | loves to do, I'll have several wip branches. wip-new-hook-
         | events, wip-update-sdk-version, wip-refactor-button-state.
         | Sometimes the branches conflict with eachother, but dealing
         | with that is worth being able to drop a task for a few days
         | while I'm stumped or blocked. I also don't tend to micro commit
         | when tests pass, just whenever I feel a smaller idea is either
         | done, or I don't know how to progress yet.
        
           | DogLover_ wrote:
           | I find it easier to use rebase for this than having to manage
           | branches.
        
             | squeaky-clean wrote:
             | Rebase works if you're comfortable with it, but it would
             | make working on multiple tasks at the same time a bit
             | harder wouldn't it? I'll be honest I'm not great with
             | rebase.
             | 
             | If you do 'git checkout wip .' it pulls in all the changes
             | committed to your wip branch into the staging area of your
             | current branch. Then you can just 'git commit -m "My
             | meaningful commit message."'
             | 
             | That's the cool thing about git though, it has a lot of
             | compatible workflows so you can do what's most comfortable
             | personally.
        
           | yccs27 wrote:
           | Oh man, I'll have to try that workflow! You describe exactly
           | how my thought process works as well, but I never thought of
           | doing that.
        
             | squeaky-clean wrote:
             | I picked up the process when I first read a blog post about
             | micro commits and wanted to try it but my company standards
             | didn't allow tons of commits to clog the history like that.
             | It feels like the best of both worlds to me.
             | 
             | I'll also add that sometimes I do break them into a few
             | commits on "real branch" if it makes more sense to do so,
             | and I use a GUI tool for merging if I need to solve
             | conflicts. I also don't really worry about commit messages
             | being useful in the wip branches. Oftentimes the commit
             | message is just "wip".
        
               | saghm wrote:
               | I've always disliked when code review tools are
               | prescriptive about my commit history (i.e. prefer that
               | each successive patch to a given CR needs to still just
               | be a single commit rather than a separate commit per
               | patch), and I ended up writing a shell function that just
               | wraps whatever command I need to use to submit a CR that
               | first swaps to a branch called `xxx-temp-xxx`, then does
               | an interactive rebase (in which I squash all the commits
               | I've made into one), then invokes the CR command, and
               | finally swaps back and deletes the `xxx-temp-xxx` branch.
               | This was made easier when I found out about `git checkout
               | -`, which switches back to whatever you just swapped from
               | last (like `cd -`).
        
         | flir wrote:
         | Two concepts are bound up together in a commit. "Publish" and
         | "Save".
         | 
         | In general our OSes aren't storing a complete history of a
         | file, so we rely on git "quick saves" (as someone else put it).
         | 
         | The git log is as much an artifact of the development process
         | as the ticket history or the code itself. You don't want to
         | publish your quick saves for someone else to have to dig
         | through in two years time - give them something a bit more
         | polished than that.
        
         | 8note wrote:
         | I always find practices about commits weird while working
         | strange
         | 
         | I usually have my changes planned out before I start writing
         | code, including which commits I want to make. Figuring out how
         | to go about making a change is a design time problem, rather
         | than implementation time imo
        
         | rubyist5eva wrote:
         | I have a guy on me team that commits basically every 5 or so
         | lines. Hell have a 30 line bug fix spread across like 20
         | commits because he never goes back and cleans up those small
         | commits that get changed afterwards, not to mention he'll merge
         | the development branch into it numerous times and _never_
         | rebased. It's absolutely infuriating reading through git logs
         | that involve his stuff.
         | 
         | His commit messages are equally maddening - "change this
         | variable to 5", "fix broken spec", "change variable to 7" ad
         | nauseam...
        
           | SketchySeaBeast wrote:
           | Assuming you squash the PR and view it holistically, what's
           | the issue?
        
             | rubyist5eva wrote:
             | PRs dont' squashed, nothing gets rebased and only merge
             | commits are allowed for anything non-local. It adds noise
             | to trying to figure out _why_ changes are made because the
             | commit messages only explain what was changed, not the
             | purpose or context.
        
               | SketchySeaBeast wrote:
               | If you're not squashing your PR's I can see the problem,
               | but I also see the other problem.
        
           | WolfeReader wrote:
           | You're lucky that you have him.
        
             | rubyist5eva wrote:
             | Not really because none of his commits have any context on
             | what the purpose any of his changes are actually for. He
             | never describes why he does anything, just that he is
             | changing something (which is obvious from the code).
             | 
             | It's the git equivalent of "useless comments" like `int x =
             | 10; // set x to 10`
        
         | jedimastert wrote:
         | I usually commit early and often locally specifically for the
         | ability to bisect during feature development. Then the squash
         | and merge is for the "public" commit history
        
         | pengaru wrote:
         | It's _far_ easier and less time-consuming to squash commits
         | than it is to tease out logically distinct changes from a big
         | mess into separate commits. The latter is particularly
         | troublesome when you require preserving bisectability, i.e.
         | _every_ final commit builds and functions. Being able to bisect
         | saves tons of time chasing bugs.
         | 
         | This is one of those "ounce of prevention vs. a pound of cure"
         | situations.
        
         | [deleted]
        
         | saila wrote:
         | I think the focus should be on atomic, independently reviewable
         | commits, not time. Sometimes, those commits are obvious and
         | sometimes it takes a while to figure it out. I don't think you
         | should feel compelled to commit on a rigid timeline (though if
         | you go too long, that probably indicates an issue with scope,
         | processes, etc).
        
       | abledon wrote:
       | Git is now my "ctrl-s" in my editor. The autosave is set to
       | 500ms. I never waste keystrokes saving now. maybe not as fine-
       | grained as this article suggests, but whenever 'jumping' from
       | rock to rock while climbing" as the starting metaphor shows, it
       | is an awesome alternative to traditional 'saving' on the
       | filesystem.
        
         | pengaru wrote:
         | FYI if you're treating git as a durable place to save your code
         | you might want to set 'core.fsyncObjectFiles = true'.
         | 
         | I've personally had my git repository become unusable when my
         | laptop lost power too soon after making some commits, before
         | the background periodic sync occurred. (XFS)
        
         | eterm wrote:
         | This is a damning indictment of file systems.
         | 
         | We have enough cheap space that we should be able to easily
         | have (non-binary) file changes have a history log in our file
         | system itself and be able to revert local changes without
         | needing the full change graph that git entails.
         | 
         | I'm all for small commits, but committing every time ctrl+s
         | happens would be an anti-pattern because ctrl+s doesn't imply
         | it compiles whereas I'd want any commit to compile. (passing
         | tests optional).
        
           | layer8 wrote:
           | Windows has File History, which I sometimes use to restore a
           | file or directory to a prior state.
           | 
           | Also, some editors/IDEs have a file history function
           | (separate from version control).
        
       | cassepipe wrote:
       | I was thinking this article would give me a way to automatically
       | commit every time the compilation succeeds after a write with an
       | automatic timestamp commit message. I think people here would
       | find it horrendous because of the unhelpful commit messages but
       | then nothing would prevent to edit the last commit message when
       | you have implemented something meaningful. Just throwing ideas,
       | don't shoot this post down.
        
         | rbates wrote:
         | Kent Beck wrote up a workflow along these lines called test &&
         | commit || revert. The idea is any change that makes the tests
         | pass is committed, any change that makes the tests fail is
         | reverted. https://medium.com/@kentbeck_7670/test-commit-
         | revert-870bbd7...
         | 
         | I believe Kent has also posted a few videos on YouTube
         | demonstrating this approach.
        
       ___________________________________________________________________
       (page generated 2022-04-07 23:01 UTC)