4 ms·
In theory that would seem like a problem, but I've never run into that problem in practice. I think this is for two reasons: 1. It actually makes for _cleaner_
by wiremine 13y ago
In theory that would seem like a problem, but I've never run into that problem in practice. I think this is for two reasons:
1. It actually makes for _cleaner_ commits, because you can group changes in whatever order/grouping you see fit. So, if you need to group part of file A, all of file C, and part of file D into a commit, you can.
2. Committing changes and publishing those changes are two separate actions. So, you are free to group your work in whatever way you think makes sense, and then publish all those changes collectively. So, if you have 16 commits, you can push all 16 of those commits together. This reduces the odds a fellow committer gets a partial changeset.
Of course, git is a powerful tool, and it will happily let you commit and push a partially finished changeset. Great power, great responsibility, yada yada yada. See http://git-scm.com/book/ch6-4.html http://git-scm.com/book/ch6-4.html.
- haberman 13y ago> So, if you have 16 commits, you can push all 16 of those commits together. This reduces the odds a fellow committer gets a partial changeset. Your argument here is that it doesn't matter if intermediate trees are broken, because no one will actually use the intermediate trees. But this approach will break anything that does use every intermediate tree, like an automated testing suite or git-bisect. EDIT: this is a bad downvote. I have accurately paraphrased the parent's point, and made a valid counterpoint. If you're downvoting me, you probably didn't understand what I am saying.
- Crito 13y agoThe idea is that you do not give intermediate broken commits to things that you do not want to have broken commits. That is why "rewriting history" is so great. Commit early and often, then publish only working code. Have your cake, and eat it too.
- haberman 13y ago> The idea is that you do not give intermediate broken commits to things that you do not want to have broken commits. But how do you know if the intermediate commits (aka the ones you want to actually publish) are broken or not? If you partially staged them, you don't know because the tree you committed never existed in your working directory. The only way to know at that point is to checkout every intermediate state later (aka after the commit) and test it then.
- Crito 13y agoYou test "intermediate" commits the same way you test any other sort of commit. They are just commits, not something special. You don't seem to be comprehending the divide between committing something, and actually giving that something to the world. In git it is perfectly natural to test after a commit. If it doesn't work, you just edit the commit. Of course testing after pushing should be treated delicately...
- haberman 13y ago> You test "intermediate" commits the same way you test any other sort of commit. They are just commits, not something special. An "intermediate" staged commit is special, as I have tried to explain many times now. If you stage a commit by using git-add to include only some of the changes in your working directory, you are committing a filesystem state that never existed in your working directory prior to committing it. You can disagree that this matters, but you cannot disagree with the above statement. It is simply a fact. Let's walk through a scenario. Suppose I am at the point in development where I actually want to create the commits that I will publicly push (ie. this is not a "commit early, commit often" scenario). All of my final changes are in my working directory, but for cleanliness I want to break them up into several commits by staging them. $ git status <git prints a bunch of "Changes not staged for commit"> $ git add foo.c bar.c $ git status <git prints foo.c and bar.c as "to be committed", baz.c is still "not staged for commit"> $ git commit At this point I have committed my changed foo.c and bar.c, but the commit does not reflect my changes to baz.c. That means that I have not actually tested that the tree state at this commit works. If I run my tests right now, they will not reflect whether the commit is broken or not, because my working tree still includes my uncommitted and unstaged changes to baz.c. I do have a couple of options now. I can stash my changes to baz.c and run the tests; then "stash apply" them if the tests pass. This is probably the best option for ensuring that my staged commit is not broken. I can also commit my changes to baz.c, then checkout HEAD^ and run the tests, but this solution forces me to mentally keep track of which commits I have tested; if there are many commits in the series, this is burdensome. Both of these solutions are entirely possible; I'm not denying this. The "stash" solution is probably the best option for this. But that said, it is fundamentally true that when you (partially) stage a commit, you can't test your commit prior to committing it. So when you write your commit message and mentally perform the process of deciding that you like this commit enough for public consumption, you don't actually know if your tree is broken or not. Even though there are workarounds, I still think this is a bit clumsy.