Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Git's commit workflow is backwards, and encourages bad habits (rory.bio)
68 points by todsacerdoti on March 29, 2021 | hide | past | favorite | 102 comments


Fixing a typo as you work on something else is not bad - that's called Boy Scouting[1] and it's totally acceptable to sprinkle small improvements/cleanups in a change.

As for getting distracted and refactoring something else - you're context switching. When you do that, you can also context-switch your repo by stashing your current changes (git stash) while you work on that tangent. Or commit your current changes to their local branch (you're liberally using branches, right? Branches are cheap in Git) and switch to a new branch for refactoring.

If you really want to write your commit first (which is a great idea, because you should know what changes you're planning to make before you start working on them!), then you can create an empty commit when you switch to your new feature branch:

    git commit --allow-empty
Write your "plan" as the first commit in that branch. Then do your work, committing frequently, and when you're done and squashing your changes into a single commit for review you now have that first commit available and waiting.

Most issues I see from people getting confused with their changes and using Git is not using enough branches for their work, not being practiced at branch manipulation, and not being disciplined and intentional about their changes. People aren't thinking about "how am I going to release this?" or "how can this be reviewed most efficiently?", and they get carried away with making a lot of changes at once instead of many small changes.

My rule of thumb is that I'm only allowed to take one step off the path/plan, anything else gets put on a todo list to revisit later.

Plan the work, then work the plan.

[1] https://www.informit.com/articles/article.aspx?p=1235624&seq...


> Fixing a typo as you work on something else is not bad - that's called Boy Scouting[1] and it's totally acceptable to sprinkle small improvements/cleanups in a change.

Different people have different standards and opinions on what's acceptable. Personally, I'm in the camp of people that would hate to see an unrelated typo fix being included in the same commit as some other change. I strive for semantically meaningful commits, and prefer the people I work with to do the same. It's fine to make such fixes, but they should be in separate commits (though they can be in the same code review request). The pain point the author of the article mentioned is very real (needing to do `git add --patch`).

> Write your "plan" as the first commit in that branch. Then do your work, committing frequently, and when you're done and squashing your changes into a single commit for review you now have that first commit available and waiting.

There are often times when multiple end commits make sense. Squashing/rebasing down to essentials is fine, but that still may be more than just one commit on occasion.


Most people however dont mind them at all and they practically do zero harm. However, forcing people to split it into two commits likely means it wont ever get done.

Because who wants to go through previous commit files to check for typos in other peoples code. People wont, either they fix it as they are noticing them or not at all.


>Most people however dont mind them at all and they practically do zero harm.

They don't do zero harm though. The git blame history gets thrashed. If I see the last change one line 15 of a file is associated with a commit titled `Enable TCP connection reuse`, I'm going to wonder what a change to a line throwing an unrelated exception has to do with that. This means I'll waste time investigating a red herring. If I need to see the blame to find out who to ask about the feature, I also get garbage direction.

The same preference for semantic commits applies to things like optimizations. Don't sneak in keep alive timeout changes in the same commit as `Add email notification support`. If a bug turns up on the email feature, I don't want to waste time potentially looking at the wrong thing.

> However, forcing people to split it into two commits likely means it wont ever get done.

That's not been my experience. They either get corrected at code review time on first release, or someone will make a semantically isolated commit for the fixes and include them in a future code review/pull request.

> Because who wants to go through previous commit files to check for typos in other peoples code. People wont, either they fix it as they are noticing them or not at all.

Not sure what point you're making here. You don't need to go through previous commits to see typos if they're still there in the current commit.


> They don't do zero harm though. The git blame history gets thrashed.

That's exactly it; the keyword here is 'churn'. There was one OS project (I'm sure there's more) that basically said that small (typo, style) pull requests will not be accepted for that very reason.

But that's where gratuitous code review, tooling, and rebasing come in; ideally a feature is complete and reviewed and tidy before it gets merged into master and 'solidified' as part of a project's history. Ideally anyway.


You have to go through them to find the typos again. So you wont.

The harm to history is marginal. It is quite unlikely that you fixed that many typos in all surrounding lines. I have yet to be confused by history like that.


You can fix them as you find them. Just save as a separate commit. No need to go back to find anything.

Typos were just an example. There are other changes that are just as harmful to history that people might otherwise think are safe to squeeze in. Examples include whitespace changes and minor refactors. All of these can really mess with history and make things confusing. Refactors in particular really mess with your head and can even make the code review step confusing if the review wasn't sent with multiple commits.

Keeping semantic isolation of commits has value in its neatness. You may be able to get by without doing so, but you'll be better off if you did.


So I will commit half file in one comit and second in another? Really not worth the risk not time.

History is not that epically useful that we should avoid cleanups.


Yes, you can commit parts of a file at a time. This is easily done by using `git add -p`.

This is a subjective matter, so I don't think your point of view here is wrong or anything, but I do disagree with it. History is something I've consulted many, many times on large code bases. It's helped save precious minutes while triaging situations where an alarm went off and customer was ongoing.


customer impact*


> you're liberally using branches, right? Branches are cheap in Git

Branches may be cheap in Git, but they're expensive in typical modern software eng. process. For every branch, a PR must be opened, code must be reviewed, full test suite must be ran, the testers must ok that the change does not require extending the test suite, and only finally after the whole ordeal we're ok to merge. That's why I prefer my branches big and meaty.


> For every branch, a PR must be opened, code must be reviewed, full test suite must be ran, the testers must ok that the change does not require extending the test suite, and only finally after the whole ordeal we're ok to merge.

Surely this isn't true for local branches on your machine? I hope you're not living under such a dystopia.


But this process is small and fast when your branches are small and fast.

Code reviews length takes exponentially longer and misses way more when branches are "big and meaty"


It should be small and fast, but depending on where you work it isn't. And trying to get a big corp to adapt to you is like trying to boil the ocean.


Just create the branch locally for your incremental changes and then when you are done, connect the remote repository to initiate the PR.


I didn't know about the empty commit, that's useful.

The approach I try to follow is below. The BLUF is I use a similar but more granular approach and agree with writing the commit before you do the work.

First, I write the commit message capturing the intended design in a file and then try to create a skeleton of API level changes with method names and stubs from my design as my first commit. I use the file as my commit message for this.

Next, as I work I commit freely locally with small commits but I don't push to remote. I do this rather than commit --amend so I can track and revert as needed if needed. I probably could just use --amend.

Last, once I have it working I squash those commits into one commit and push to remote, then merge in changes from master if any and repush, and then start cycle over.

I tend to do this at one level below the issue I am working, so I then still have multiple commits for an issue, one per sub-issue. I will sometimes leave these as is in the PR, or sometimes I will squash these into a single commit as well. Which I do depends on how active the branch I'm targeting with the PR is, how big the commits are, and the extent of the changes.


Really depends on other changes. Say you change some variable name since whoever was there last forgot to rename something while they did refactoring. Couple days later someone fixes a bug that is related to this variable in some other way. Now you can't simply back port the bug fix commit into earlier release because it relies on a commit that introduces a feature that is not wanted/needed. Obviously fix is simple enough either edit the commit to also contain the variable change or make a tiny "dummy" commit that just contains the fix.

Now whoever is making this decision is cursing you since you could have just made the dummy commit in the first place and prevented this extra work that went into figuring out when the bug fix commit alone wasn't working/compiling.


> As for getting distracted and refactoring something else - you're context switching.

Which absolutely should be a new branch and probably a different ticket.


In addition to empty commits or rebasing work in progress commits, git stash accepts -m/--message and you can write a "proper" commit message when stashing work in progress. Some client apps (I've seen VSCode do it) will even kindly move that message from the stash into their commit message writing box on popping the stash.


My only issue is that if you fix something small and include that in an unrelated feature or bug fix commit, is if you have to do a "git revert" you are then reverting both items.


That's why you don't squash before merging. If you merge the original commits (and make a separate commit for the minor fix), you can revert the problematic commit without affecting the rest of the feature.


But making a separate commit for the minor fix is onerous once your working copy has accumulated other changes. That's what the OP says -- you have to use "git add -p" and that is onerous.


Why would something with such a good concept need to be tied to a gendered term?

How about calling it "camp grounding"?


The Boy Scouts of America did a lot to promote Leave No Trace and helped it become a common practice.


It's not appealing to any kind of gendered stereotyping though. It's a quote from the founder of "The Boy Scouts Association".


I suggest you take your complaint to the English language office. In Dutch, that organization would be called "padvinders" (lit. pathfinders, i.e. trackers) which shows that the concept itself isn't gendered.


Because it's a Boy Scout rule?


Your suggested term works, too. But why is it bad that a good concept has a gendered term?



The non-gendered term for "Boy Scouts" is simply "Scouts" or "Scouting" [1]. So if you need a non-gendered name, just call it "Scouting".

And the word 'scouting' already means "moving ahead of a group to gather information", which makes sense in the software engineering context too.

[1] https://en.wikipedia.org/wiki/Scouting


This is a bit of a sensational title. Developers are empowered by Git to use a workflow that works for them. This is exactly what the person has done, they've made a workflow that works for them.

One is free to commit any time they like, it's not "Git's commit workflow", Git itself does not have an opinion on when you commit, just how.

Bad habits are not encouraged by Git, people get lazy, or complacent, and learn bad habits.

There are GUIs that allow you to stage and commit hunks of code intuitively, but GUIs are often shunned by people who spend a majority of their time in the CLI - however I am sure Vim and the like have some kind of tool for doing something similar.


I disagree. In any tool some things are easier and others are harder. The easier ones will be done more often. We can parcel out blame between users and tools, or we can be more productive and work to improve both.

Git add -p reminds me of ed. And sure, you can technically write anything in ed. Still, there's a reason we improved on it.


> Git forces you to write your commit message at the end of your coding session

You could create a commit and —amend work into it if that is the route you’d like to take.


This in combination with a `git diff` in a split shell works very well for me. For adding changes, I often use `git add -p` - this also gives a nice opportunity to think about a change again. As a bonus, if I did not yet push, I can extend the commit (using --amend) or roll back to it when doing experimental changes. There is also the option to `git stash` some work away.


Hell, you could write it down in a separate text file if it’s really that big of a painpoint.


At that point I think the case for a tool like git-plan is pretty strong.


I think most teams use a bug tracker for this sort of thing, tbh.


Magit changed how I commit by making it much easier to split up changes. (I'm sure another gui would work well)

Edit: I think a buffer of lines you navigate is just the right metaphor for working with a bunch of text. It's why line editors are generally considered obsolete.


> I'm sure another gui would work well

I'm not, I've not seen anything else like magit's diff views: they provide a great overview of the entire state (of the working copy or staging area) and allow very fine and nonlinear staging/unstaging.

While technically `git add -p` provides the same capabilities, magit's allowance for jumping around and staging and unstaging (and reverting / killing) as you wish and go is a huge boon, it requires significantly less pre-planning and remembering that `git add -p`'s linear and blinkered (one hunk at a time) workflow

The only thing that I've not found perfect is reverting parts of an existing commit (e.g. re-reading your log you realise that you added debugging crap to a commit): magit will create a staged revert and an unstaged re-add, which is nice to move stuff out of a commit but a bit confusing for straight reverting it. And even that is still miles ahead of everything else I know of.

The only thing magit is lacking is fixing interactive rebases: it beats the pants off of doing interactive rebases manually, but i'd like it to compute "dependencies" between patches so it stops me from moving a patch above its dependency, or at least tells me beforehand (as that usually generates huge conflicts which would be better handled by not moving the patches that way because it's an error, or splitting the patch being moved beforehand).


I prefer magit to other but GUIs, but I think selecting changes is the area it's comparatively weakest (compared to other GUIs, it's far ahead of -p). I'd like a better way to use a mouse, and a way to only commit parts of lines (I know this would involve non-trivial workarounds, but that's why I'm using a git porcelain).

Edit: I also dislike hunks, they never correspond to what I want reliably. Another annoyance is I think magit is quite good at the low level selection in general, but it's hard to get a high level overview because I'm always collapsing and un-collapsing things.


I find that Lazygit provides a nice UI for staging, too: You can state an entire file or just lines(!) from a file.

I wish it allowed me to stage a hunk, too. But I make do with staging all lines from that hunk. It is not a lot more effort.


git add -p works quite well from the CLI.


I'm glad it works for you. For me there's a crucial jump in fluency of using something graphical to select lines that makes willing to be more precise.

I think a buffer of lines you navigate is just the right metaphor for working with a bunch of text. It's why line editors are generally considered obsolete.


Sorry, that comment was pre-caffeine and it probably seemed like I was dissing on the GUI. I meant to suggest git add -p as an option for those who don't want to use Magit or similar, or as an intermediate step between git add . and a GUI diffing tool.

Git add -p is still pretty useful for reviewing individual changes, but slicing finer than that, or editing patchsets directly as text, is definitely a dark art, but one that I'm glad that I have learned through repeated trial and error (e.g. recognizing that the first column must always be a space, plus, or minus). I would probably have added to my prior comment that a specialized diff editor paired with git add -p might be more useful than doing so with a usual text editor.


As a further option, there is also git add -i which is not a great UX and it has its own weird DSL with oddities, but still a slightly "higher level" than git add -p for when people need or want something less fine-grained than git add -p from the command line without installing another git porcelain.

git add -i lets you get the status of files in the working directory, add entire files, revert entire files, or patch individual files, all from a single UI "session". You can do all of the same stuff with appropriate pathspecs to the individual commands such as git add -p just/one/file-i-need.md, but git add -i is an option for those that want an "almost GUI" for that.


No problem. That all makes sense.


Commingling (supposedly) unrelated changes in a single commit isn't indicative of any problem with the vcs.


I cannot overstate how much this post expresses the feeling I have had for a very long time but could not pinpoint and I love the premise for the call to action. People who love Git will no doubt say that the current way is how Git is supposed to work because one must think in an atomic mindset. You declare that you like the whole sum of changes that you made, then commit it with a single commit, OR you have a series of commits and if you realize you made a mistake, change/amend it or do some more questionable things like a hard reset to before the series began, OR just squash the commits when it's time to merge

If I'm wrong about the previous point on how one would carry out the post's vision with current Git, then I would attribute some of that to my opinion that Git CLI isn't very good UX-wise and is why people have made a mountain of GUI tools just for Git

Honestly, I know that Git supports the kind of workflow the post describes, but there is some psychological barrier to making seemingly "permanent" commits because my coding workflow doesn't work that way. It works more like the way the post describes. I like to toy with code, make mistakes, backtrack a ton of times, sometimes restart from zero, or even if there was somehow the "magic pill" solution, it would be awesome if it could somehow automatically associate the files you worked with for a specific feature and know that some subset of the modified files are irrelevant, or at least reduce the number of context switches each time you like a new addition to a giant feature

Our idealized next generation of voice assistants might be able to handle such tasks.

"I need the files I was just playing with added"

"Are the lines 3-10 from main.c related to these?"

"Yes but not lines 8-10"

"Ok, I've hidden the changes that you believe are irrelevant. Try testing again. Does it still work?"

Unfortunately our voice assistants are absolutely nowhere near the kind of fluidity that this kind of voice-based workflow demands and if attempted today, would be extremely frustrating or cause a lot of mistakes. I can't even tell Google or Siri to go backwards on a conversation if I misspoke. I need to restart the entire conversation like I'm speaking to a toddler


I solved this problem for myself by writing a Git extension that mimics the workflows at companies like Google/Facebook. It's very good for writing many small commits and exploratory coding, and I can't go without it anymore. If you suffer from the same problem in the article, you can also try out my tool: https://github.com/arxanas/git-branchless. Please send me any feedback (email in bio).


It seems to me that the author is conflating two very different activities, akin to how writers must learn to separate the act of writing from the act of editing: Attempting to edit or to polish when writing impedes writing, impedes just letting words flow.

Stuck? Add a parenthetical note (TK - need X to happen to Y here - TK) and move on. (Why TK? Because it rarely occurs in English words and so makes a useful, searchable marker for changes or challenges to be added or addressed later.)

Coding is akin to writing. Get in and stay in the zone, let it flow. Don't worry about the other things.

If you want to commit to support rewind and blame, do so, just don't push (or don't push to the real remote, push to a working remote set up for the purpose, one you reset periodically). Commits are cheap and git provides plenty of tools for massaging them to make sense (and even appear to be in whatever order you think best!) after the fact before pushing them for real. Between patching and cherry-picking and squashing and other capabilities, the tools are there.

Committing is like editing. Well, more like publishing. It is the act of recording your work...

...and telling OTHERS what you did.

They are different activities. Both can be hard work.

Do the context switch and do the second in the way that makes the most sense to your workflow, to the workflow you share with others. It might be tedious and it might be a pain...

...for example, if all changes need a distinct issue, so you have to cherry-pick the typo, create an issue for it, commit the change referencing the issue, etc., etc. I'm glad I don't work there, wherever that there is. I know theres like exist, though.

I'm glad the author developed a tool and approach that helped them, but git isn't to blame for the conflation of two remarkably distinct activities.


> git add --patch can help here, but it's still tedious work.

This is pretty much the operative line of the post. Rather than invert my whole development flow, I just use a UI like Magit which makes patch commits trivial.


I just aliased "add -p" to "git ap" and use lots of "commit --amend" and everything feels easy


I use it all the time and abbreviated it to 'gap', and "git commit --amend" without a comment to 'gam'.

(and 'git push --force' to 'git yolo', then later to 'gpf', but don't tell anyone)


I've started doing microcommits recently which helped with that exact issue highlighted in the article. My current workflow, on a side project as a solo developer, is to commit as soon as I have any relevant piece of functionality (even if it's just an empty React component that I'll then build out) which also makes it trivial to come up with a commit message. When a feature is done (or part of the feature if it's big enough already) I create a PR which I briefly review. Not as deeply as I would with an unknown code, just want to make sure there's nothing obviously wrong. While an unrelated refactoring is still bundled in the same PR, it doesn't matter because it's a separate commit and I rebase/fast-forward into master.


You don't need the ideological purity of commit messages in order to have useful commit history.

Get 90% of the way there and for the rest if you've got unrelated changes that are readable, just move on, commit them together and eat the pain.

That's my belief, but of course git permits others. Git is very low level, it's a tool to build a workflow for you.

My workflow involves tolerances for imperfection. I believe in developing like I move and act: my movement has easing, compensation, and feedback. I focus more on being quick to patch errors than on never making one.

But I don't write code for a Mars rover and I don't know if I would have a different workflow there.


This article talks about doing fixup changes while working on the "plan".

The utility offered though doesn't address the fact that now non-related changes are still bundled together.

We've just managed to write the git commit message earlier?....


If I understand the proposal correctly, it works like a stack.

So you're working on "git plan --commit-message='important feature'" or whatever the syntax would be.

Then you encounter a place where some refactoring would be really helpful, so you do

"git plan --commit-message='refactor: ...'"

Any changes made during this plan won't show up in the original git plan.

I'm not sure if this is how it works, but that's how I understood it.


That is not how it works, but it's an interesting idea. My worry is that it's a little fragile in the same way that vanilla git is fragile - you can accidentally start working on a new task and mess up your stack.

In reality, git-plan just keeps a directory of draft commit messages for you, and when you run `git plan commit` you can choose one of them to use as the template for your commit message. Essentially, it runs `git commit -t <YOUR_PLAN_FILE>`.

(I'm the author)


Well, as the author said, it's an initial idea.

I suppose an ideal tool would be for me to highlight a bunch of lines in the IDE, say "These code changes are part of plan: [ABC/XYZ/Create a new plan...]".


Funny you say that, because I built that as well: https://github.com/synek/codeline

It's even earlier in development than git-plan, but the `commit -m "some message"` command works.


I just press D in gitup for unrelated changes and continue to spam with commits that are related to feature, works well.


For me, code reviews force that discipline.

My workflow is to edit code, figure out bottom-up how it really works, then look at all the mess, realize I could never get review approval, and stash it. Then I start over top-down, make the same changes again -- wiser this time -- add in comments which make sense to others, and commit to a new branch. Repeat with another new branch until everything in the stash has been incorporated.

With `git plan` I'd have to skip over the 1st exploration phase. Desirable, but irreducible.


My workflow is the same. The results of the exploration phase are like a prototype - plan to throw it away, keep the learning, then build the final, elegant version.


Git's workflow is bad, but this doesn't fix it at all because the real problem in the first paragraph comes when that first paragraph occurs after you've already made some commits, and that can only be solved by either uncommitting a bunch of stuff or committing the next code in the wrong order and then rebasing to rearrange and squash commits.

> to facilitate the feature you're working on you decide to make a small architectural change elsewhere in the codebase

Imagine this happens _after_ you've already made a bunch of commits. So you write some code. You make some commits. And then you run into a wall where you suddenly realize that you really should change something else and do the code in an early commit differently.

Writing your commit messages in advance doesn't solve anything related to git. If you actually already knew all of the commits you'd need to make, you wouldn't ever suddenly decide half-way through to make an architectural change that you hadn't planned to make from the beginning. But you _don't_ already know all of the commits you're going to need to make. That's the problem, and this proposal doesn't address it.

So now you make a new commit for the architecture change, and then you make a dummy commit for the code that uses the new architecture change, and then you git rebase interactive to move the dummy commit after the earlier commit and mark it as a fixup, and you move the architecture change commit before the whole thing, and then you pray that nothing is broken in the process.


I agree it's a problem - but I don't think there is an easy solution nor that the article presents a solution.

The problem was just that I was distracted or forced to solve a different problem than I had planned. Making a plan doesn't change that. If anything, it leads to ending up with a planned commit message that is still unrelated to the changes (which seems worse than having no commit message at all)?


Most GUIs let you stage individual lines quickly and efficiently to achieve exactly what the author laid out in the beginning. Make whatever changes while you're in the zone and then spend a couple minutes grouping your changes on a per line basis. Maybe it's more cumbersome if your want to stay in the command line but that's a choice. Use the tools that fit your workflow.


My impression after reading this is that the author needs a better git client. magit, SourceTree, or Fork (my personal favorite at the moment) let you stage individual lines and chunks, which is life changing.

If you find a typo or something you want to be in another commit, stage that line and commit it and carry on. Use rebase and cherry pick later to move commits around as you want.


My first thought was 'oh no, not yet another git command!" but I get where the author is coming from.

However, the dangerous part is including a refactor in an unrelated change. Good luck backing that out if you need to. Personally, when I'm in this situation I just park what was supposed to be doing and then do the refactor separately.

It helps reviewers and is more transparent.


Bundling unrelated changes together is the main issue in the article. The author may not like hearing this but Git is a collaborative tool and thus when you submit your code you aren’t just committing code that you understand but someone that will also review your code — to understand as well.

Bundling 12 unrelated changes does a disservice to your other team members.


I use the git CLI for most things, but if you want to do line-by-line commits, then you're really much better off using a GUI. I recommend Sublime Merge. It starts up almost instantly, so you can leave it closed most of the time and pop it up with `smerge .` in your terminal when you need it.


As others have stated, your habits can be much better in this regard if you use a git GUI client that allows you to stage only certain lines / hunks with ease.

I personally didn't like git GUIs and only ever used it from the command line until the release of Sublime Merge[1], which imo is hands down the best git client. Exactly what I need, not loads of extra cruft. Plus the performance you expect from the people that made Sublime Text.

I almost immediately paid for a license after I started using it and still actually use git from the command line for a variety of other things, but for staging changes Sublime Merge is invaluable.

[1] https://www.sublimemerge.com/


Nice idea, I encounter this problem often during work. I usually end up doing the lazier "git add -a" where a couple of unrelated small fixes get bunched together in a larger commit.

Sometimes I do take the time to organise the changes into multiple commits, but that process is very prone to making mistakes.

The most annoying part is when I accidentally forget to add a crucial one-line chunk belonging to a particular feature I'm working on, so that I have one commit "refactor: ..." that accidentally has an important config change or a one-line change that actually belongs to the feature. So now the feature commit doesn't represent a fully working program. Very annoying.

I'll try this out, see if it works any better. Hope it does!


I don't really have a problem untangling my changes into different commit. In fact, I often untangle them into separate pull requests. Though for very small changes, that's overkill.

I consider small fixes unrelated to my main change acceptable if they're in the same file. If not in the same file, that means they're probably easy to put in a different commit or PR. Which one of those it is, depends on how big the change is, and whether it constitutes a meaningful change.

Having to think about this after I've done the work has been done, seems to be the right time to think about it for me. Though maybe not for the author. For people who prefer a different workflow, I guess it's nice to now have that option.


Currently, I would try to get around the situation posed by simply using fine grained git add to specific files.

But here is a situation I find backwards. If I am doing work, and then I go to commit. I do not want git to do a merge or tell me there is a merge conflict. I mean... I do want to know there is a merge conflict, but I do not want git to try and merge and dump a bunch of merge conflict information in my folders/files.

What I want to do, but git does not seem to have a simple way of doing, is... forget I am trying to commit. Pull down the repo to the latest. Put my files back in. Then let me do a git status, git diff so I can see what my changes are clobbering. What is the correct set of git commands to get it to do that?


I think this is an interesting idea and could be helpful. I started using Magit in Emacs a few months ago, so detangling unrelated changes is a piece of cake now, so I don’t feel like this would actually be a benefit for my workflow. ¯\_(ツ)_/¯


Smaller changes spend less time in code review and avoid workflow problems in git.

In fact, I think git outright encourages you to make lots of small diffs.

Feel free to squash groups of your commits before you merge in.

Makes git bisect debugging a hell of a lot easier as well.


Shout out to emacs' brilliant git porcelaine magit. It makes doing a bunch of disconnected stuff 'in the zone' and then staging and commiting whichever lines and refs you want totally straightforward and easy.


There is where I love working with good dev tools.

In VS Code, you click the source control button, you instantly see a list of everything that has been modified.

Click on any particular file, you get a visual diff. Press the "+" button, you stage the selected file/files, add the commit message and check them in. Continue that until all the changes are in place, properly sectioned off with appropriate comments.

Yes, this doesn't apply to anyone using the raw git commands, and knowing those is important. But in getting stuff done and keeping everything nice and neat, developer tools to the rescue.


I like it; I like it a lot.

At first I bristled at the notion that the workflow is wrong, but this places the "todo list" front and centre. That's an integration of workflows that makes sense.


I've never needed to pre-write my commit message or felt that was an issue. However, I do think git could make it easier to context switch. It would be pretty neat if you could switch branches without losing your working changes - so they are there when you return. I understand git stash exists, but that is two extra steps, you have to give it a name, and then remember which stash contains what. It would be nice if you could just leave the working changes with the branch itself uncommitted.


I have a little bash function that goes over all your stashed diffs and let's you either apply it or continue. This way I can resume work faster by finding the right stashed state quickly. Here's the code if anyone is interested: https://gist.github.com/juancampa/69b065c5c09a775ea72f6c8c77...


I agree with the author that the need to write descriptive commit messages (and untangle off-topic commits using `git add -p`) does take one out of the "flow" state, but in my experience these post-work, commit-time self-checks are very useful: I run `git diff --cached` on the staged changes and review them to see what's going into the commit and often catch some bugs or forgotten pieces at this time, so overall I'd say the loss of flow is worth it.


If it's just fixing typo or other trivial fixes, in most projects just use a single commit and say "while I'm here, also fix typo/etc." in the commit message is acceptable, unless the main change has higher than normal chance of getting reverted later.

Even if that's not appropriate, gut add -p really isn't that hard (and git commit/add -a is a really bad habit you shouldn't use unless absolutely necessary, e.g. you are making the initial commit).


The idea of writing a commit message in advance is nice, and possibly helpful in focusing, but I don't understand the added value with respect to the issue stated. Commit messages aren't the challenge, rather it is planning out what goes into a commit.

As many others have said there are already great UIs to help you manage these things retroactively, but there is probably no good substitute to properly planning your work and executing on that plan (if order is your top priority)


> You've got changes in 12 files, and many of those changes aren't related to each other. What do you do?

IntelliJ products allow you to select only relevant lines in commit dialog.


So, in Agile development it is important to do things in priority order. A typo should practically NEVER be fixed if it is not in the comments. So, this is not a GIT issue. This is doing the wrong thing at the wrong time!

And, I really, really dislike the term Boy Scouting. It is anti agile. The only result is usually that the none senior developers are changing things that simple is not important and causing new bugs. Formatting code etc, I'm fine with.


Is this sarcasm or.. I can't tell.

Or is it "Agile" to never fix spelling errors because there's always a bug which is more serious?

Is it agile to not vaccum the house because the toilet upstairs is dripping? Or am I mixing up agile with Agile now?


I guess I could tell you but I also guess you will not understand. Have you ever had a bug in production on a site that can sell for 10 000 000€ on an evening just cause some guy corrected a stupid spelling mistake? I have.

What I'm saying is that all these issues goes into the same funnel as everything else and get prioritized. If you feel that all these small issues is a problem. Fine, fix them. Otherwise, your senior developers will spend more time reading unnecessary pull requests about garbage than producing real code.


I don't have a senior developer, but I have a ton of people submitting pull requests to me. Sounds like you need to adopt testing. Isn't that part of Agile? Or was that in agile? Can't remember.


To expect manual or automatic tests to cover all changes is naive. If people start to make changes that is not related to the actually task. The risk of missing something is kinda obvious.

You (and the op) is barking up the wrong tree. Surely you have to understand it is not the fault of git that ends you up in this stupid situation. It is a broken process.

Edit: grammar, not all :)


If git plan helps get the work done, that's great for you. I don't really understand the need to dunk on git in passing (a lot of people do this). I mean, there is no demonstration that git, by itself, encourages bad habits.

For example:

> Neither of those choices are good, but git doesn't give us much choice.

and

> Git forces you to write your commit message at the end of your coding session - after you've already turned your thoughts into code anyway.

No, git tends to not force anything, it gives you tools to stash, commit, rebase, push, etc. you are free to use them at any point of your coding session. There is little to none workflow made mandatory by git, which is how various workflows can be supported by it (github, patches over emails, git-flow, etc.)

> If you context-switch during your coding session, git is not aware of it. In-fact, git isn't even a part of the picture until after you've finished writing code.

maybe that's a problem of your workflow, not the tool, and again if git plan helps you with part, that's cool. This is however does not look like a typical git situation to me.

> The "right" thing to do is to spend time un-tangling your changes, staging them in groups and committing with well thought-out commit messages.

The encouraged thing is to commit early, commit often (http://www-cs-students.stanford.edu/~blynn/gitmagic/ch05.htm...):

> So commit early and commit often: you can tidy up later with rebase.

In your examples, my workflow would be to use git between each context switch.

> Picture the scene, you're in the zone working on a new feature in your codebase when you spot a typo and fix it.

magit-status, mark the line, commit it with a quick message "fix typo". If you find that magit is cheating, then (1) it feels like cheating, in a good way, and (2) git add -p file is still quite easy to do?

> Then, to facilitate the feature you're working on you decide to make a small architectural change elsewhere in the codebase.

oh, let's git stash first

> Finally, before finishing your session you decide to refactor some code in one of the files you were working on.

Ok but first, let's do a quick git commit, then work on that. Eventually I rebase interactively to write better messages, clean things up, then push.


I do not understand the benefit in the described scenario: Why not branch for the typo and the code refactoring? Is it a bad habit to reflect your changes after you coded them?

I see the benefits for a backlog in Git by using git plan, though. I would have used Gitlab Issues for this...


I solve this by committing often without a meaningful message, and rebasing afterwards.

Maybe that could be taken further - have autocommit every few seconds, and then have a `git add --patch`-like workflow, but one that selects time ranges instead of line ranges.


When doing this kind of in-work fixes, I use "add -p" to make an independent commit only of that specific change.

Later with "rebase -i" I move all such commits at the start of the branch, and in case deploy them with an earlier merge.


Hey folks, I'm the author.

Context-switching is hard. Having the discipline to prioritise effectively is hard, using git branches effectively is hard, and building tools to magically make it easier is...hard.

Git-plan doesn't solve this problem outright, but I hope it moves in the right direction.

I do think that once you have draft commit messages in your workspace, it is possible to build new tools that consume them to help you context switch. For example, a tool could automatically stage hunks for you, based on the draft commit message you wrote.

There are some great thoughts and criticisms here and I'll be taking them all onboard for the next couple of versions of the tool. If anyone wants to contribute, PRs are welcome and I can help out as needed.


If you have a good code review system, like Gerrit or Rietveld, you can do what I do.

Every single commit and upload is immediately followed by `git checkout -B master origin/master`.

Use WIP tags for things you intend to keep working on and download the patch and upload new patch sets as you continue. Using the code review tool as a substitute for branches and continuously doing work off of a clean master has changed my life.


fugitive.vim makes it very fast to do laser-focused partial commits, you just have to remember to do it 2-3 times a day. It's really very good. I think Magit in the Emacs universe does more or less the same.

Git-gui (bundled with Git) doesn't look that nice, but is also pretty fast for making partial commits.


Is anyone else having certificate issues?

For some reason your website is blocked by Tulane university.

I have no idea why.


The site has a Let's Encrypt cert so it should be fine. I made some DNS changes to it yesterday though so maybe that has something to do with it.


I can email the SSE Dean or the IT head to find out why. This seems weird.


This is the entire reason I use SourceTree. It adds a great UI to the patch command


TL;DR IMHO author does not know the basic tools, suffers consequences and invent something that does not even fixes the problems they shouldn't have suffered in the first place.

Proper use of "git gui" and "gitk --all" makes doing the right thing (independent semantic commits) become the easiest thing, remaining in the flow.

After your flow session, you can cherrypick or git rebase -i at will to create branches after the fact.

gitk looks dated but it's rock solid and dead fast even with huge repos. Its only actual drawbacks are some smart but not-well-discoverable features.

the missing gitk documentation https://gitolite.com/gitk.html




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: