2

Workflow I have is to do very frequent commits and pushes, then later when I am ready, combine the commits into a single commit (with histedit etc.) to cleanup the log.

With git, I would do a rebase and push. The dangling head left behind would not litter my log, and would eventually be garbage collected.

With mercurial, I end up with multiple heads. And if I close the branch to get rid of the stale heads, I end up with a million closed branches that still show up in the log. That defeats the original purpose.

How do you have such a workflow in mercurial without completely screwing up the log? Is there an alternative workflow that does work under mercurial?

NOTE that the frequent commits also get pushed out to a repo (just for safety). Which means I can't quite use things like strip.

Ziffusion
  • 8,779
  • 4
  • 29
  • 57
  • You *can* use `hg strip`, it's just a big pain. Consider setting up the frequent small commits to use secret phase, so that they do not get pushed. If you do need to push them explicitly, force them back to secret phase afterward, and strip them elsewhere if/when needed. – torek Nov 18 '17 at 00:11
  • Strip doesn't work once you have pushed the commits out. I mean, it works on your local repo fine, but then you get them back next time you pull. They are there in the repo forever. And you end up with multiple heads. You can close a branch to get rid of the heads, but the history / log remains painfully cluttered. There was a link below describes 3 ways of purging the unwanted branches. But all of them are painful enough to make this workflow very tedious. https://www.mercurial-scm.org/wiki/PruningDeadBranches – Ziffusion Nov 18 '17 at 04:07
  • That's why I suggested marking them secret. Once pushed you must `hg strip` them from every repository, which is that "big pain". Lazy Badger's suggestion (disabling publish in a secondary backup repository) will also work, though now you need three repos: "work site", "secondary backup", and "publish point". Instead of all of this, though, the Evolve extension is clearly on the right track, and I don't know why it's not yet part of standard Mercurial. – torek Nov 18 '17 at 15:46

2 Answers2

2

Consider the evolve extension, which is best explained in this post, though it's not bitbucket specific and is widely supported in Mercurial environments. You probably have it installed and just need to enable it.

Once you grok it it's the best of all world. It lets one commit replace another -- it obsoletes the other even if it's already pushed. It lets you re-write commits in a way that doesn't break already pushed commits. Think of it as git --amend or git rebase but safe for already pushed stuff.

When you do a push of a changeset that obsoletes one or more other changesets you, push obsolete markers for those changesets and anyone who subsequently pulls from that repo has the obsoleted changesets replaced in their history/log with what you've pushed. The obsoleted changesets exist still, but they don't clutter the log.

I hope we get something similar in git soon -- a few people have started work on similar features.

peak
  • 105,803
  • 17
  • 152
  • 177
Ry4an Brase
  • 78,112
  • 7
  • 148
  • 169
  • 1
    Thanks! A couple of questions. Docs say that evolve enabled repos exchange obsolescence information. What happens in a mixed environment? What would a non evolve enabled repo see? Docs also say that evolve will only let you rewrite changesets in one of the two mutable phases (secret or draft). Does that mean that this mechanism cannot be used for commits that have already been pushed? – Ziffusion Nov 18 '17 at 09:21
  • One more. I have a lot of these dangling closed branches that I would like to clean up. Is there a way to use evolve to prune a commit and all its descendants? Like strip, but for pushed commits. – Ziffusion Nov 18 '17 at 09:43
  • "You probably have it installed and just need to enable it." The Evolve extension is not currently shipped with Mercurial. You need to get it separately. – Faheem Mitha Mar 09 '19 at 23:30
0

While @Ry4an suggested really The Best Way (tm), you can use another way wth only "classic" released tools

  1. Use [phases] publish=False on push-target (read and grok phases) (see also After pushing to a review repository, "abort: can't rebase immutable changeset" on rebase and http://www.logilab.org/blogentry/88203 for intro into phases)
  2. Use any history rewriting methods on your side
  3. If pushing mutated history to not-publishing repo still will create additional heads (I'm too lazy to test it for you) - eliminate all unwanted anonymous branches (with "dirty" history) by using dummy merges - you'll have a lot of mergesets in history, but only one real head
Lazy Badger
  • 94,711
  • 9
  • 78
  • 110