[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)