Is it good to commit files often if using Mercurial or Git?
It seems that it is suggested we can commit often to keep track of intermediate changes of code we wrote… such as on hginit.com, when using Mercurial or Git.
However, let's say if we work on a project, and we commit files often. Now for one reason or another, the manager wants part of the feature to go out, so we need to do a push, but I heard that on Mercurial or Git, there is no way to push individual files or a folder… either everything committed gets pushed or nothing get pushed. So we either have to revert all those files we don't want to push, or we just never should commit until before we push -- right after commit, we push?开发者_如何学Go
The best way to manage this (whether you are using Mercurial, Git or any other revision control system) is to make sure your work is done on branches which correspond to these "parts of features". If there is even a small chance that some portion of work will need to be released independently from other work, it should have its own branch from the start.
This gives you the flexibility to push just the "part of the feature", and is much better suited in the case where the "part of feature" and some other "part of the feature" both contain changes to the same file.
The nice thing about using Mercurial or Git here is that managing these branches is trivial, so the cost to creating and using them (even if they turn out not to be necessary) is minimal.
Now, you can't always foresee everything. If you do end up stuck in the situation you describe, though, it's easy to get out of. Say you had 100 changesets locally (not yet on the server) and you wanted to just push the current contents of 1 file. Create a clone of the repository you're working on back to the server revision, copy the file over, commit, push, and integrate back. In Mercurial this would look something like the following:
$ cd ~/project
$ hg clone http://server/project/trunk trunk-oops
$ cp trunk/shouldve-branched trunk-oops/shouldve-branched
$ cd trunk-oops; hg addrem; hg ci -m "We need to organize better!"; hg push
$ cd ../trunk; hg fetch ../trunk-oops
Develop on branches.
Have a release branch and feature branches. Merge in each feature as it becomes available.
It is good practice to commit often. In your case, it seems like you need to start tagging and/or branching more often.
To extend and clarify what others have said: committing often and flexible pushing are not mutually exclusive.
You do want to plan ahead, and make your commits such that you'll be able to adapt. This means two things: you need to make sure you really commit often, and you need to branch (as in git) frequently. If your commits are small, it'll be easier to reorganize them later should you need to selectively group together part of your work. And if your branches are well-organized, you may already have a branch which is exactly what you want to push.
Compare these two:
One branch, few commits:
- A1 - B1 - C1 - B2 - A2 - B3 - C3 (master)
Many branches, many commits:
M1 - M2 (master)
/
o - A1 - A2 - A3 - A4 - A5 - A6 (topicA)
|\
| B1 - B2 - B3 - B4 - B5 - B6 - B7 (topicB)
\
C1 - C2 - C3 - C4 - C5 (topicC)
Now, if you want to release any of those three topics as-is, all you have to do is merge it to master and push! If you want to release half of topicA, and that half is taken care of in commits A1, A3, A4, and A6, all you have to do is rebase topicA to place those four commits first, merge the last of them into master, and push. The remainder of topicA (A2 and A5) can hang around for further work.
M1 - M2 ------------- X (master)
/ /
o - A1 - A3' - A4' - A6' - A2' - A5' (topicA)
(Commits denoted by A1', ... because with git, a two commits with the same contents but different parents are actually different commits.)
精彩评论