Alternative routines when using Mercurial Hg
I would like to get your opinion on which of the following routines should I use, or which of them is more desirable, when using Mercurial. Suppose t开发者_高级运维hat I have the latest code.
First routine is following:- Do my work
hg commit
- Repeat steps 1 and 2 if needed
- When I'm ready to push I
hg pull
,hg update
hg merge
,hg commit
hg push
Second is:
- Do my work
- when I'm ready to commit I
hg pull
,hg update
hg commit
,hg push
The thing is that, as far as I know the first alternative is the one which most of the developers (should) use because, unlike in second option of usage, it provides the opportunity to use local repository, as it is a normal thing for DVCS.
My colleagues encourage me to use the second way, because that way I avoid branching and later possible problems with merging (because in past, somehow, they had such problems), so I stay on trunk development line. I guess that the first option is the option that should be preferable because merging is something that shouldn't be afraid of in DVCS, unlike in CVCS, and it gives me the opportunity of using local repository.
There is not any difference in the work you will be doing in both cases:
with the first workflow, you will do a merge in step 5.
with the second workflow, you do the exact same merge as part of the update in step 2.
The first workflow feels safer to many since you're working on already committed work. This means that it's trivial to get back to a clean state if the merge turns out to be complicated: hg update -C .
.
But you can actually get your original files back even with the second workflow: hg resolve --all --tool internal:local
will redo the merge that hg update
started and select the original version for all files.
The real difference is that the first workflow better shows what actually happened. With that workflow you can present your change in smaller and more logical steps. That helps a lot when your colleges try to understand what you did (code reviews) and with future debugging (with hg bisect
).
You can get the best of both world with hg rebase
. That lets you make small and logical commits and then finally move those commits on top of the work done by your colleges. There wont be a merge changeset in that case -- nice and rich linear history.
So if you have this history after the pull:
... [a] --- [b] --- [x] --- [y] --- [z]
\
[d] --- [e]
where you have created x
to z
, then a normal merge would create this history:
... [a] --- [b] --- [x] --- [y] --- [z]
\ \
[d] --- [e] ----------- [f]
With a rebase you get
... [a] --- [b] --- [d] --- [e] --- [x'] --- [y'] --- [z']
where x'
to z'
are the rebased versions of x
to z
(different changeset IDs because they have different ancestors).
I use rebase like this all the time and I feel it gives the best overall history. Just remember not to rebase changesets that have already been made public: rebasing modifies the changesets, but if the changesets are already public, then it's difficult for you to modify the other copies. The result is duplicate changesets and confusion.
Basically, you already answered the question yourself:
The first routine is the "default" one for DVCS because it takes advantage of the typical DVCS features
(local repository, faster commits because no network is involved, more detailed history because of many small commits vs. few big ones...)
Using the second routine is not "wrong" or "bad", but you have to be aware of the fact that you're using a DVCS as if it were a CVCS, so you intentionally choose not to use some of the advantages of a DVCS (see above).
People who are long-time CVCS users (like your colleagues, probably) often prefer the second routine because that feels more what they already know.
Plus, merging works better in DVCS than CVCS, so their "possible problems with merging" argument is probably only because they had problems in CVCS in the past and assume it will be the same in DVCS (which is not the case).
精彩评论