While trying to work out an integration between Kiln and Bamboo I ran into an issue that Fog Creek support indicated might be a problem of having too many topological heads in my repository. We typically have a pattern of closing a branch prior to merging back into a main branch but that clearly gets forgotten from time to time.
$ hg head -t | grep ^changeset: | wc -l
1361
My understanding is that those heads need to be communicated one way or the other when pulling from the hosting Mercurial server to know which heads need to by sync'd. That's a lot of wasted effort given that over 1100 of those heads are completely dead to us -- so I'd like to get rid of those heads!
It's fairly straightforward to identify the heads I want to eliminate:
$ hg log -r "heads(all()) - ( head() and not closed() )" --template "{node}\n" | wc -l
1199
I initially thought it would be fairly straightforward to clean this up:
Unfortunately, I ran into a couple of issues:
Any ideas or suggestions on how I should proceed? Is my iterative merge idea sane? Are one of the two ideas for where to start from more reasonable than the other?
Any help is greatly appreciated!
The fastest way to do a no-op merge is via hg debugsetparents. For example:
hg update REV1
hg debugsetparents . REV2
hg commit -m "No-op merge"
Note that the . after debugsetparents is not a typo, but refers to the parent of the current checkout. Also, note that hg debugsetparents allows you to perform a pseudo-"merge" against a direct ancestor, which is not normally allowed by a merge. While this should not have any harmful effects for Mercurial itself, other tools that interact with the repository may be confused, so you should avoid misusing hg debugsetparents where one parent revision would be an ancestor of the other.
Second, note that there is usually little point in using --close-branch to close already merged branches. The closed flag is in practice only used by hg branches, and you can use hg branches --active and hg branches -a to elide branches that have no active heads (similarly, head() and heads(all()) and not closed() as a revset for all branch heads that aren't active or closed). Therefore, a simpler solution may be to get rid of all those topological heads that exist only to close branches.
Some (possible unrelated) notes
hg heads is templateable command, you can (instead of grep) have -T "{node|short}\n" in heads command or something like it (string per changeset in output)Solution
You can create temporary Merger-Branch (better - from current tip, see below) and perform dummy merges all unwanted|not needed heads into this Merger (dummy merges are fast and non-interactive, i.e. easy automated), and merge Merger back to tip (also maybe with dummy merge for sure, while it isn't needed at this step - Merger head will not be changed at all after all merges).
Merges topological heads into Merger can be (I suppose) automated - I can't have full working code for you, only hints:
Three-liner from wiki can be used as shell-script with single parameter "REV to merge"
In hg -y merge --tool=internal:fail REV REV is any identifier of merged revision (changeset-id, local revision number), which you can get from list of hg heads -t -T "TEMPLATE" and pipe it into xargs, which perform shell-script from above
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With