3 ms·
> No. Breaking your work up into several small, "logical" commits is exactly the right thing to do. The author is not arguing against making small, logical com
by stevelosh 16y ago
> No. Breaking your work up into several small, "logical" commits is exactly the right thing to do.
The author is not arguing against making small, logical commits. He's arguing against making a ton of changes in your working directory, then running `git add file1, file2... ; git commit` a bunch of times in a row to record a series of commits.
The problem with this is exactly the one he mentioned: almost no one ever goes back and makes sure each commit actually builds and passes tests.
After they finish making a series of, say, three commits they just go ahead and push. It's only weeks or months later when someone bisects that they find out the first commit was broken without the contents of the third.
Mercurial users use MQ for this process, and to me it seems like it's a better and safer method with an uglier UI.
With MQ, once you were ready to create your three commits you would say:
`hg qnew file1 file2 ... --message 'Fix the foo bug'`
`hg qnew file2 file3 ... --message 'Add feature bar'`
`hg qnew file4 file5 ... --message 'Add feature baz'`
Now you've got three patches that appear (mostly) as normal changesets in your repo.
You can `hg qpop` back to the beginning of the set, run your tests, fix anything that's broken and add it into the patch. Then you would `hg qpush` the next patch and do the same thing.
Once you know that all three patches represent a working state you can `hg qfinish --all` to turn them into vanilla commits.
Yes, it's more work, but you've got three "logical" commits that actually work, instead of three "logical" commits that might hopefully work.
MQ is also great for the open source workflow you mention, where you send your patches to a mailing list (for example), get feedback, and rework them.
If someone tells you changeset X has problem Y, you can just `hg qpop` back to the patch, fix Y, refresh the patch with that change, and retest/resend.
If you want even more crazy power, you can make the directory containing your patches a Mercurial repository, which lets you track the evolution of your patches over time. It's very weird and meta, but extremely powerful.
- masklinn 16y ago> Mercurial users use MQ for this process, and to me it seems like it's a better and safer method with an uglier UI. MQ lets you do the exact same thing as the interactive rebase. It's not like it forces you to go back and ensure every single patch is correct after you've qfolded some together or reordered them. > You can `hg qpop` back to the beginning of the set, run your tests, fix anything that's broken and add it into the patch. Then you would `hg qpush` the next patch and do the same thing. And you can do the exact same thing with your git commits before pushing them, last time i checked MQ had `qpush -a` and did not force you to run your tests between two qpushs. > Yes, it's more work Indeed. And if you have no problem with that more work, you can do it just as well with git. MQ doesn't magically make people care. > If someone tells you changeset X has problem Y, you can just `hg qpop` back to the patch, fix Y, refresh the patch with that change, and retest/resend. No you can't. Because if it's a changeset (rather than a patch in a series) then you've already qfinished it and pushed it to a public repository, and you're now rewriting public history. I don't like git for a number of reasons, but this is a terrible strawman: git provides all the tools needed to ensure each and every commit is correct (whereas bazaar, for instance, doesn't. Not without untold amounts of pain anyway), and I've seen a number of blag posts and comments which recommended exactly that approach: tinker on your local branch, rewrite to your heart's content, and before you push anything to remote test each commit individually. There is nothing which prevents you from doing that, just as there is nothing that forces you to do that with mercurial.
- stevelosh 16y ago> MQ lets you do the exact same thing as the interactive rebase. It's not like it forces you to go back and ensure every single patch is correct after you've qfolded some together or reordered them. It doesn't force you, but by providing easy ways to push and pop patches it encourages it. > And you can do the exact same thing with your git commits before pushing them, last time i checked MQ had `qpush -a` and did not force you to run your tests between two qpushs. What's the git equivalent of `hg qrefresh`? What about when there are other commits on top of the current one? > No you can't. Because if it's a changeset (rather than a patch in a series) then you've already qfinished it and pushed it to a public repository, and you're now rewriting public history. In this case I meant that you don't qfinish the patches right away. You leave them as patches while you submit them to the mailing list. You're talking about pushing to a public repository, which is different than patch bombing a mailing list. In that case the "MQ" way to do it is to push your patch repo somewhere, and other people can grab your patches that way. It's a bit more complicated, but it does have the nice effect of giving you a "history" of a series of changesets. I don't know how you'd do that with git. > I don't like git for a number of reasons, but this is a terrible strawman: git provides all the tools needed to ensure each and every commit is correct (whereas bazaar, for instance, doesn't. Not without untold amounts of pain anyway), and I've seen a number of blag posts and comments which recommended exactly that approach: tinker on your local branch, rewrite to your heart's content, and before you push anything to remote test each commit individually. There is nothing which prevents you from doing that, just as there is nothing that forces you to do that with mercurial. I agree that you can do those things in git -- I'm only say that it doesn't encourage it. The existence of the index actually encourages doing it the wrong way: checking in states of code you've never tested. No, Mercurial doesn't force you to do it right, but MQ and its qpush/qpop provide an easy way to do it the right way if you want to, and versioned patch queues makes it easy to track history of patches if you need that kind of power.
- masklinn 16y ago> What's the git equivalent of `hg qrefresh`? What about when there are other commits on top of the current one? There is no direct equivalent as far as I know (short of using one of the quilt-like tools built on top of git) apart from amend for topmost commits, but it's easy enough to do with rebase —interactive (or rewrite in mercurial). > In this case I meant that you don't qfinish the patches right away Then they're not changesets, they're patches. > You leave them as patches while you submit them to the mailing list. You can do that just as easily from a local branch. > You're talking about pushing to a public repository, which is different than patch bombing a mailing list. I'm not talking about anything. > It's a bit more complicated, but it does have the nice effect of giving you a "history" of a series of changesets. I don't know how you'd do that with git. I don't either. > I agree that you can do those things in git -- I'm only say that it doesn't encourage it And I disagree with your assertion that mercurial encourages it. > The existence of the index actually encourages doing it the wrong way: checking in states of code you've never tested. Not any more than the ability to `qrefresh` only a subset of your working copy. > No, Mercurial doesn't force you to do it right, but MQ and its qpush/qpop provide an easy way to do it the right way if you want to And it's almost as easy to do the same thing with git.
- jamie_ca 16y ago> The author is not arguing against making small, logical commits. He's arguing against making a ton of changes in your working directory, then running `git add file1, file2... ; git commit` a bunch of times in a row to record a series of commits. > The problem with this is exactly the one he mentioned: almost no one ever goes back and makes sure each commit actually builds and passes tests. Right. For git, IMO the right way to do this is: $ git add -p # stage the first bunch of changes you want to commit $ git stash save -k # push all the unstaged changes to the stash $ # build your code, run tests, whatever $ # repeat until it builds clean $ git commit # record the clean (possibly fixed) commit $ git stash pop # get your other original changes back Repeat as needed until all your stuff is committed. If you can't make a subset of your changes build clean, then it's not independent and should not be committed standalone.