Using Git Add -P for Fun (and Profit)
Key topics
The art of crafting a tidy Git history is sparking a lively debate, with some swearing by the power of `git add -p` for selective commits, while others champion GUI alternatives like JetBrains IDEs, Magit, and Lazygit. As commenters weigh in, it becomes clear that there's no one-size-fits-all solution, with some advocating for the flexibility of command-line tools and others preferring the visual intuitiveness of graphical interfaces. Meanwhile, a contrarian view emerges, questioning the value of meticulously curated commits, only to be countered by arguments that well-crafted commit histories can serve as valuable documentation. The discussion highlights the diverse workflows and priorities of developers, from easing rebasing to generating meaningful documentation.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
4d
Peak period
55
84-96h
Avg / period
15.6
Based on 78 loaded comments
Key moments
- 01Story posted
Dec 10, 2025 at 12:27 PM EST
27 days ago
Step 01 - 02First comment
Dec 14, 2025 at 9:06 AM EST
4d after posting
Step 02 - 03Peak activity
55 comments in 84-96h
Hottest window of the conversation
Step 03 - 04Latest activity
Dec 16, 2025 at 9:51 AM EST
22 days ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
Maybe consider putting your energy into a good documentation inside the repository. I would love to have more projects with documentations which cover the timeline and ideas during development, instead of having to extract these information from metadata - which is what commit messages are, in the end.
If someone else decides your implementation of something is not good enough, and they manage to get enough buy-in to rewrite it from scratch, maybe they were right to start with?. And if your history is not clear about the why of your changes, you have 0 to defend your work
But that's not actually the reason I use "git add -p" the most. The way I use it is to exclude temporary code like traces and overrides from my commits while still keeping them in my working copy.
However, it doesn't makes "git -p" less useful when the idea is to separate what you want to publish and what you want to keep in your work zone, be is your working copy or a dev branch.
As always with git, it is not very opinionated, it lets users have their own opinions, and they do! Monorepos vs many repos, rebase vs merge, clean vs honest history,... it can do it all, and I don't think the debates will ever settle on what is an "antipattern" as I don't think there is a single "right" answer.
Commit messages are documentation. If you have a good commit history you don't need write tons of documents explaining each decision.
Hoo boy I guess you never tried to use `git blame` on years-old shit huh?
>But then comes somebody and decides to just flush your well curated history down the toilet (=delete it and start somewhere else from scratch) and then all the valuable metadata stored in the history is lost.
This doesn't just accidentally happen. There are tools to migrate repositories and to flush ancient commits in huge repositories. If you curate your commit history, this is probably never necessary, or may only become necessary after decades.
>Maybe consider putting your energy into a good documentation inside the repository.
Commit messages are documentation for code, basically. `git blame` associates the messages with individual lines and lets you step through all the revisions.
>I would love to have more projects with documentations which cover the timeline and ideas during development, instead of having to extract these information from metadata - which is what commit messages are, in the end.
The commit messages are for detailed information, not so much for architectural or API documentation. This doesn't mean you should get rid of commit metadata! Eventually, you will find a situation where you wonder what the hell you or someone else was doing, and the commit message will be a critical piece of the puzzle. You can also leave JIRA links or whatever in the message, although that adds a dependency on JIRA for more details.
One of my git habits is to git reset the entire feature branch just before opening a PR, then rebuild it with carefully crafted commits, where i try to make each commit one "step" towards building the feature. This forces me to review every change one last time and then the person doing code review can also follow this progression.
These benefits hold even if the branch ultimately gets squashed when merging into main/master. I also found that even if you squash when merging you can still browse back to the PR in your git repository web UI and still see the full commit history there.
It's useless for all but the code preservation part, it doesn't tell you anything.
> But then comes somebody and decides to just flush your well curated history down the toilet (=delete it and start somewhere else from scratch) and then all the valuable metadata stored in the history is lost.
I would be very angry if someone deletes my work, why would I accept that? When my colleague throws my work into the bin, I will complain to my superior, they pay me for it after all.
> Maybe consider putting your energy into a good documentation inside the repository. I would love to have more projects with documentations which cover the timeline and ideas during development
That's what commit messages are? They provide the feature that you can click on any line in your codebase and get an explanation, why that line is there, what it is supposed to do, and how it came to be. That's very valuable and in my opinion, much more useful than a static standalone documentation.
First you think of commits as backups, then you think of them as a code distribution. Later you see them as a way to record time. What has been a useful insight to me was, what time is a prerequisite to: causality. Now I see that a VCS is less about recording actual history, but about recording evolution dependency, causality and intent. Also I perceive my work less to be about producing a final state of a codebase, but about producing part of the history of a codebase. My work output is not a single distribution of code, but documented, explainable and attributed diffs, i.e. commits.
How does this happen? I haven't run into this.
> Maybe consider putting your energy into a good documentation inside the repository
I'd say both are valuable.
I use git log and git blame to try to understand how a piece of code came to be. This has saved me a few times.
Recently, I was about to replace something strange to something way more obvious to fix a rendering issue (like, in some HTML, an SVG file was displayed by pasting its content into the HTML directly, and I was about to use an img tag to display it instead), but the git log told me that previously, the SVG was indeed displayed using an img tag and the change was made to fix the issue that the links in the SVG were not working. I would have inadvertently reverted a fix and caused a regression.
I would have missed the reason a code was like this with a big "work" end of the day commit.
It would have been better if the person had commented their change with something like "I know, looks weird, but we need this for the SVG to be interactive" (and I told them btw), but it's easy to not notice a situation where a comment is warranted. When you've spent a couple of hours in some code, your change can end up feeling obvious to you.
The code history is one of the strategies to understand the code, and meaningful commits help with this.
My commit messages are pretty basic “verbed foo” notes to myself, and I’m going to squash merge them to mainline anyway. The atomic commits, sometimes aided by git add -p, are to keep me nimble in an active codebase.
Dark mode text: oklch(87.2% .01 258.338)
Background in both modes: oklch(14.5% 0 0)
See here: https://jsfiddle.net/kmtwf4g3/
I think the fuckup of the website author is that the background is black instead of white in light mode. Otherwise the text colors would be fine as they are.
Lesson learned!
So instead of having to `git add -p` several times to pick apart changes from the worktree, the worktree always goes into the graph and you can `jj split` to pick them apart after.
The main difference, it seems, is workflow: git's "prepare then commit" vs jj's "commit then revise".
Currently I do make use of `git add -p` just like grandparent, but I also feel a psychological burden: I will often leave like 3 or 4 separate 2-line changes in the worktree because I don't wanna bother with the ceremony right now, but my perfectionism also resists me putting a lump commit. That's jj's main appeal to me. It amends my work in, then supposedly let's me sculpt it when I'm ready with less of that ceremony.
> I confess I'm still pretty new to git. I haven't had a very long time to wed myself to git's index and its presence makes me do extra ceremony that I resent whenever I want to polish my graph for my personal projects.
Have you realized, that Git versions the index yet? It was written by a filesystem guy, who (I think) considers the filesystem to be a shared space, so Git doesn't consider the filesystem to be its playground. Think of "git add" less of preparing things for the next commit and more of telling git that it can consider some state to be part of its world model. Your repository does not consist of everything below a directory (it can actually span across multiple randomly located directories), it does consist of everything that was once added to the repository.
> The main difference, it seems, is workflow: git's "prepare then commit" vs jj's "commit then revise".
I do the latter just fine in Git, but yes "git add" is a fundamental part of my workflow. I often add some lines already to the index and start writing the commit message, then trying something again in the working directory and either throwing it away or also adding it, before I finally commit. To me the index is a feature.
> but my perfectionism also resists me putting a lump commit
Sounds like you will use a VCS correctly.
> I don't wanna bother with the ceremony right now
I don't know what exactly you consider to be the "ceremony", but I think nearly any git GUI/TUI will let you add lines by selecting with the cursor and pressing a key. The good ones also allow you to edit this. This also works in the opposite way: removing or editing specific lines from an already existing commit. In my experience carefully adding lines results in less mistakes than adding everything and then carefully removing lines, but YMMV.
'jj edit' seems to correspond to 'git checkout', '@-' is '@~'. '@+' is not possible in Git, because a commit can have an arbitrary amount of children, Git might not even know about, not sure how JJ does this.
'jj split': use 'git commit --amend' and unselect changes or 'git reset --soft' to an older version, recommit the first part and then take the original commit on top. A git commit consists of a state, not of a diff so putting some commit on top of another that already contains part of the changes results in splitting the former.
'jj describe': 'git commit --amend'
'whoops, insert commit in the middle': just commit
'jj squash': either 'git reset --soft @~2' then 'git commit -c/C' or 'git reset @~' then 'git commit --amend' or 'git rebase' with squash or fixup. The later is possible from some other commit by using 'git commit --fixup' or even 'git absorb' (I think also exists in JJ).
Most of the time, when working on a new commit I have a few changes related to recent commits. So _when I'm done with all that_, I commit selectively the new work, then dispatch the rest among the other commits:
Sometimes, I use `commit --fixup` instead of the automatic `absorb`. Anyway, I tried Jujutsu for a few weeks, some was good and some was bad; it didn't "shine" enough and I went back to pure Git.The things you commit can always be different from what you test. In fact, if you know what you are doing, it is a feature to be able to create commits like this without testing. I certainly don't need to test my "Fixed typo in comments" commits...
>How do people handle that? One way would be to follow it up with git stash, running tests, and, if necessary, git amend, but that can get cumbersome soon.
Well, your CI system should be testing for you. But if you must test it locally, `git rebase` can either pause between steps or execute commands between steps. Finish making commits. If you made, say, 3 commits, then do `git rebase -i HEAD~3` and do break/exec as desired.
https://archive.today/Ig42c (has issues with Cloudflare DNS)
https://web.archive.org/web/20251214151943/https://techne98....
I like it especially in concert with git commit --amend, which lets me tack my newest changes onto the previous commit. (Though an interactive rebase with fixup is even better)
I’ve had the opposite problem: forgetting to add new files.
> I like it especially in concert with git commit --amend, which lets me tack my newest changes onto the previous commit. (Though an interactive rebase with fixup is even better)
No need for the rebase to be interactive:
Any good solutions for this around?
For now I've adopted running `git status` after `git add -p` to make sure there's no untracked files, but it feels a bit clunky
There are many other plugins for vim and emacs (e.g. magit) that enhance one’s git workflow.
Lol or they could use VSCode's integrated source control and stage stuff manually that way. Both are better than bare `git add -p` in my opinion.
the / (search) command to search unstaged hunks for a specific keyword rather than having to jump through all the individual changes you've made when there's lots.
and the e (edit) command to manually split out two changes that end up in one hunk that I'd rather have in individual commits.
for one, it lets me create small patches of related stuff. There's nothing wrong with major patchsets in general but it makes it harder to cherry-pick little fixes to old stable branches for example
two, I notice other developers making me do the work for them because crap sneaks into their commits, like debugging statements or accidentally removed hunks. Instead I have to do "git add -p" when reviewing their commit.
Essentially, it's a first pass staging area you can review what you did. beautiful.