Well, you don't, so... don't do that. Same thing goes for Perforce; you can already create multiple changelists that you commit independently, so it's easy enough to create a bad commit, because it contains only some of the changes you've got locally.
What you're supposed to do in Perforce of course is to create your changelist, shelves the others, make sure your proposed changelist works independently, and commit it only when it does. Which is analogous to what you're supposed to do with git:
- stage parts of files
- `git stash -k'
- check it works
- `git stash pop'
- commit
But let's be serious here - the true advantage of git comes when you do the pro move.
- stage parts of files
- commit
- (90% of the time) it's good
- (10% of the time) bzzt... it's bad
Now, if you were using Perforce, in the 10% case, you'd be stuffed. Somebody would come over to your desk.
- (them) "Your commit is broken"
Now what can you do? There's no denying it... you gone done fucked up, and there's no denying it.
But with git, you have options. So let's try that again.
- (them) "Your commit is broken"
- (you) (confident tone of voice) "Ah no, you are using git incorrectly, you forgot to git fetchpack
--inflate-upstream-probability-leaves --deny-downstream-packs
--integrate-sideway-arguments --discombobulate-flat-file-compressed-alignment-jobs
-P -Q -J 5 -N 311 -X 0771 -R 0x134774"
- (them) (uncertain)
- (you) (confident gaze. Straight into their eyes. YOU = TIGER)
- (them) (increasingly uncertain)
- (you) (unblinking gaze. You have the upper hand. YOU = 2 TIGERS)
- (them) (wanders off to try your technobabble)
- (you) (fixes your commit)
That's a personal problem. Don't blame the tooling for a bad coworker.
As long as a change or refactoring stands independently of the intended feature change, there is often value in keeping that fine-grained version history. It replicates your thought process at the time in the history messages, gives more manageable git-bisects, etc.
If you can't reliably look at the modified files and pick out what changes stand independently then this approach is obviously not for you, or at least you're gonna need some help from your tooling.
TeamCity has the concept of a 'delayed commit' that is submitted as a patch and tests are run. If the tests fail the patch is not accepted. You can also do a ghetto version of this in any system just by running a local copy of your CI server. Push to its repository target and have it run the tests. If it works push it out to the real build server, if not then there's no problem just force-pushing an amended commit since everything is still local.
Alternately you can commit the independent changeset and then stash everything else and run a build/test.
Obviously you can't always pull out an independent changeset and in those cases you should commit the whole thing at once. But a lot of times it's not actually that difficult to identify independent steps that could be built/tested independently.
Aah, sweet, someone else who uses Perforce! I've been wondering, do you use version control as:
1. a way to record logical changes to files (e.g. implement two features without making any commits, then when you're done, pick out the files/chunks that encode each feature and create commits out of them),
2. a record of history (e.g. just start writing code and make a commit every time you compile/run tests without unexpected failures),
3. something else?
I've found it very painful to apply my git-adapted workflow to Perforce: I _want_ to just start coding, testing out various possible design choices and implementations instead of only theorizing about them, but can't (e.g. "I wonder if I could factor out these methods + fields into a different class?" Perforce: oh well, I guess I should write it down somewhere to remember for later. Git: branch my current work, spend five minutes sketching an extraction, then realize it's insane and continue working). Am I crazy and just don't realize ow much better the Perforce model is?
I actually came to quite like it, but the workflow was sometimes a bit tiresome :( When I found myself the situation you describe, potentially wanting to make an additional change while already working on another, I did exactly what you suggest: add a todo item, and carry on until I'm done with the task at hand. Then start my second change with nothing checked out, so I can undo checkout on everything should I make a mess.
This works, and you get used to it, and of course many would say that it's a better approach - but it would be nice if the Perforce client tools could be a bit more imaginative.
As for how I think of version control, if it's git, #1. If it's Perforce, #2, plus #3 - backup and distribution.
I don't know how much value I get from being careful about my commits with git, but it does make me feel better (which I suppose could be reason enough). On the large-scale, goal-oriented projects that I've used Perforce for, worrying about logical changes has never felt very important. Does it make a big difference if you have one commit that implements 3 features, or 3 commits? When you're trying to fix a bug, you don't really mind either way, because (a) bugs don't respect feature boundaries, (b) all the features are non-negotiable, so it's not like you can back one out and carry on anyway, and (c) the project is large and fast-moving enough that even if you could, there'd be a good chance that actually, you couldn't.
What history tends to come in useful for when it comes to this sort of project: finding the code that corresponds to a particular build that you have a bug report for, and finding who made a particular change so that you can ask them about it (using the imeline view say). These both work fine whether you make granular changes or not.
You might want to be a bit more careful about things if you're working on changes that might want to be merged into another branch on an individual basis. (Suppose you're moving spot fixes from release branch to main branch - some you'll want, some you won't.) But you usually know when you're making this sort of change, and so you work that way anyway.
What you're supposed to do in Perforce of course is to create your changelist, shelves the others, make sure your proposed changelist works independently, and commit it only when it does. Which is analogous to what you're supposed to do with git:
But let's be serious here - the true advantage of git comes when you do the pro move. Now, if you were using Perforce, in the 10% case, you'd be stuffed. Somebody would come over to your desk. Now what can you do? There's no denying it... you gone done fucked up, and there's no denying it.But with git, you have options. So let's try that again.
There's an xkcd about this.The advantages, I think, are clear.