top | item 39381505

How to commit part of file in Git

70 points| thunderbong | 2 years ago |newbeelearn.com | reply

102 comments

order
[+] torblerone|2 years ago|reply
Splitting up commits is totally underrated and seen rarely. I see colleagues over and over again plumbing 4 kinds of changes into the same commit. Good luck reverting the one change that caused an outage.
[+] cedws|2 years ago|reply
Crafting good commits is a skill that nobody seems to care about. In fact, nobody really seems to care about learning git at all despite it being one of the main tools in software development.
[+] quectophoton|2 years ago|reply
And on this topic, another underrated feature that everyone seems to hate is merge commits.

If you use rebase on your own branch, but merge commits on the stable branch (whatever name you use for it), you get both things:

* Small individual commits with the size and ordering that the original author intended on their branch.

* A "commit group" that describes that set of changes for the sake of future maintainers' sanity, and that can be atomically reverted.

More so in PR-based flows. You can have `git log --first-parent` display only the PR merge commits[1], and `git log --no-merges` display the linear history.

[1]: Assuming you actually put useful info on those commits. If you use GitHub, those merge commits can be set to default to PR title and description.

[+] yjftsjthsd-h|2 years ago|reply
> Good luck reverting the one change that caused an outage.

Surely you'd revert to the last good release? I'm sure you could revert a single commit and re-release, but it seems slower (you have to find the right commit to revert, and make sure that the result works correctly) and riskier (since now you're effectively rolling forward to a combination of commits that's never been deployed before)

[+] fuzzy2|2 years ago|reply
People will actually revert commits? For real? At work? Where do I get to sign up?
[+] chipweinberger|2 years ago|reply
just don’t spend more time splitting up commits than you would have reverting change

usually you should err on the side of keeping the commits together, unless you’re close to release, patching a bug in release, etc.

[+] jerpint|2 years ago|reply
Mostly it’s just that git makes it unnecessarily hard to do atomic commits across a file
[+] 000ooo000|2 years ago|reply
Also check out `git add --patch`'s cousins over in `git checkout` and `git reset`. I probably use reset --patch more than add, as I'll usually have a file full of relevant changes with only 1 hunk i want to 'unstage', so I'll stage the whole file and unstage the irrelevant hunk.

I use `git checkout --patch` mostly when splitting a big commit into smaller commits, retroactively. I start an interactive rebase, chuck 'break' before the big commit, then I start pulling the changes 'forward' from the big commit into the working directory with `git checkout --patch big-commit-hash */path.ext`. Sometimes this works out easier than popping a commit off and re-committing everything seperately, particularly if I already have a commit with a detailed message.

[+] ggregoire|2 years ago|reply
VSCode handles this very well too: select the lines you want to commit and do "Git: Stage selected ranges"
[+] DavidVoid|2 years ago|reply
I'd be careful with that feature though because it used to have an absolutely awful bug (and it might still tbh, I haven't had it confirmed that it's fully fixed yet).

https://github.com/microsoft/vscode/issues/96104

If you staged selected ranges it could change the line endings of the whole file from CRLF to LF. It's very easy to miss since it doesn't show in the normal diff, but then you end up with merge conflicts galore later on.

[+] ukuina|2 years ago|reply
VSCode's interface to Git is superior to Git-native. Adding the concept of Sync, simplifying branching, so many niceties.
[+] pantalaimon|2 years ago|reply
`git gui` seems to be the easiest solution to me. The interface is not pretty, but it does what one would expect and it’s fast.
[+] zilti|2 years ago|reply
Why use git gui when you can use magit
[+] danhorner|2 years ago|reply
I came here to say this. `git gui` is nearly ubiquitous and has saved me for years from learning how to use `git add -p`. I don't use many graphical git tools but its options "stage hunk" and "stage line" are more intuitive and fine-grained than the hunk-splitting in `git add -p`
[+] rk06|2 years ago|reply
git etensions do a better job
[+] gomoboo|2 years ago|reply
For those in the JetBrains world, you can do this easily with changelists: https://www.jetbrains.com/help/idea/managing-changelists.htm...
[+] jmaker|2 years ago|reply
Totally, been doing it for a long time in IntelliJ and the other JetBrains IDEs, still stunning colleagues by simply check marking blocks or lines to commit the way it conveys hopefully the most meaning, so there is little if any dependence between the logical units across the commits, so as to be able to revert easily if necessary. And then the PR tells a story rather look like a frightening blob of shuffled ASCII chars.
[+] wilg|2 years ago|reply
GitHub Desktop does this very well. Highly recommend!
[+] hallman76|2 years ago|reply
As does SourceTree. Also recommended.
[+] parentheses|2 years ago|reply
This article should mention `lazygit`. That's one of the best ways to customize hunks without committing to `emacs`.

Magit's USP is that it's a great interface for those who already use (or are willing to use) `emacs`. `lazygit` is a great interface in its own right.

[+] hexfish|2 years ago|reply
+1 for lazygit, and I say this as someone who has used git exclusively on the cli for years and still continues to do so. It's just that lazygit makes staging hunks, squashing and rebasing such a joy.
[+] jraph|2 years ago|reply
I customize hunks without Emacs and with git add -p.

I use git rebase and git add/reset -p left and right.

I will definitely checkout lazygit though, thank you and others in this HN submission for the mention, looks useful.

[+] palata|2 years ago|reply
I find `git add -p` easy enough. Maybe I learned not to address random stuff while working on a particular thing, though.

But that's the beauty of it: git makes it easy for anyone to use their favourite tool (be it CLI, TUI or GUI) :-).

[+] gooseyard|2 years ago|reply
I didn't know about git add -p when I started using magit and thought it was an amazing magit-specific feature and went around cluelessly telling everybody about it. Later when I was experimenting with a different editor I realized my folly, and have come to find that I prefer git add -p, since I often want to provide multiple paths or a glob etc when its time to add to the index.

Something I found that I like about the approach is that sometimes while working on a change, some unrelated code will catch my eye that I want to fix but not as part of my next commit. Being free to make the edit, knowing that I'll see it again later when staging changes, is nice because I would often otherwise forget to go back and revisit the thing I saw. The git add -p sessions then wind up being an opportunity to decide what changes go into each commit, etc. I do burn myself occasionally by having an unrelated edit that is in a hunk that can't be split- I suspect there are tweaks to diff I could make to help with that but have yet to overcome my apathy wrt research.

[+] petepete|2 years ago|reply
I've used tig to do this for 15+ years. It's effortless. I know lazygit is more modern and has more features, but tig does this so well I have no need to change.
[+] collinvandyck76|2 years ago|reply
I kept running into an issue with tig where it couldn't break apart a hunk, or otherwise couldn't stage a part of one. I never figured it out by the time I gave lazygit a shot. Now that I've used lg in anger I only wish I had invested in it sooner.
[+] praash|2 years ago|reply
I have used patch-adding almost exclusively for a few years. It really helps me stay aware of my workspace and avoid committing temporary tweaks. I can also keep semi-permanent personal tweaks uncommitted in my workspace and get constant reminders if I still have an inline debugging flag activated.

It's unlikely to remember this feature's existence and benefit from it without habitual usage.

[+] poidos|2 years ago|reply
magit with vim mode is awesome for this. just visually select the lines, commit, done. so good.
[+] lsllc|2 years ago|reply
Sublime Merge does this really well.
[+] icywonder|2 years ago|reply
git-cola handles that nicely too.
[+] IshKebab|2 years ago|reply
The only sane way to do this is with a proper IDE. Doing it via the command line is pure masochism.
[+] dgellow|2 years ago|reply
Why? I use git add -p absolutely all the time, its really simple to learn
[+] loloquwowndueo|2 years ago|reply
It’s perfectly doable in the command line. Utilities like git-gui make it fairly easy to stage and commit chunks or lines. Git plug-ins for vim or eMacs (the article mentions magit) are also quite efficient. You don’t need a bloated IDE for this.
[+] Rebelgecko|2 years ago|reply
I do hg split (which I think this is based on? Or at least it's very similar) all the time and it's fine. I guess an IDE makes it a little easier to select regions that don't line up with hunks?
[+] arcanemachiner|2 years ago|reply
lazygit is my answer to this problem... and so many others.
[+] RheingoldRiver|2 years ago|reply
does anyone use Sublime Merge for this? do you like it?
[+] lsllc|2 years ago|reply
Yes! I’m pretty happy with Sublime Merge. It’s also cross platform (like Sublime Text) which is very handy.