Adding support for deleting Git remote branches, direction forward

123 views
Skip to first unread message

David Carr

unread,
Sep 15, 2012, 3:15:50 PM9/15/12
to hg-...@googlegroups.com
As discussed previously, I'm working on enhancing Hg-Git by adding support for deleting remote Git branches in the same way you would normally use Hg to delete remote bookmarks.  The main pain-point this addresses is that there isn't currently any way to perform this operation using Hg-Git (you need to instead use Git or some other tool).  This approach was preferred over a new command ('hg remove-git-branch', for example), since I believe the current thinking is that, as much as possible, Hg-Git should match Hg's normal behavior.  In this case, that means that using Hg with Hg-Git to push/pull remote Git branches should exhibit similar behavior to using Hg to push/pull remote Hg bookmarks.

Here's what the wiki has to say about deleting remote bookmarks in Working with remote repositories:

"To delete a bookmark from a server, delete it locally first, then use push -B on the deleted name."

The main implementation of this in Mercurial is in mercurial/command.py in the push method.  It first converts any specified bookmark options into revisions to include in the push, then calls push on the repo, then goes through the specified bookmarks again to use listkeys and pushkeys to synchronize bookmarks.  From this, it looks to me like there are three main ways we should hook in to implement support for this feature:
  1. Wrap commands.push.  If the remote is a git repository, call special logic to delete remote branches if appropriate.
  2. Add logic into the push method in our existing repo subclass.  We'd need to somehow gain access to opts['bookmark'], which isn't passed in... which might really mean that this is a false option, and is a subset of option #1.
  3. Add logic into the listkeys and pushkeys methods in our existing gitrepo peerrepository subclass.  We'd need access to the GitHandler instance to do anything meaningful.
I started down the road of #3 first, and got it to the point where it appears to be accomplishing the desired change (deleting remote git branches) as appropriate.  Currently, in my implementation, it is doing an additional send_pack() for each branch that needs to be deleted.  I don't think that this is likely to be a big deal in practice (since deleting remote branches hopefully isn't a frequently-used operation), but it seems inelegant, as it would have been possible to delete them all at once during the send_pack in push() if we had the appropriate information (a la option #1 above).

Putting performance concerns aside for the moment, option #3 has a side-effect I hadn't realized up-front.  By having listkeys() return the accurate list of remote bookmarks, Mercurial now is able to recognize divergent bookmarks (as documented in Transferring bookmarks on the wiki).  This feature was only added in Mercurial 2.1.  Thus, when in a divergent bookmark use case, previously, Hg-Git would leave the local bookmark alone silently (but fail on push, I believe).  Now, in Mercurial 2.1+, a message "divergent bookmark master stored as master@default" is printed and an incoming bookmark is created with a suffix.  In previous versions of Mercurial, a different message "not updating divergent bookmark master" is printed and no incoming bookmark is created.

As an Hg-Git user that uses a recent versions of Mercurial, I'd prefer being able to use a workflow based completely around bookmarks (including divergent bookmarks, when appropriate).  When this support is available, I don't think there's a need for creating local tags for remotes any more; from a user perspective, it's a redundant way of storing and displaying the same information.

Our current policy is to support the version of Mercurial shipped with the latest Ubuntu LTS build and subsequent Mercurial releases.  Currently, that means Hg 2.0.2 (shipped with Ubuntu 12.04 LTS).  From the Ubuntu wiki LTS page, I don't expect there will be a new LTS release until 2014.  That means that, unless we change our support policy, we need to support a workflow without divergent bookmark support until the next LTS release.

There are a few ways we could handle this:
  1. Don't pursue a deeper integration with bookmark workflow yet.  Use option #1 from above to support deleting remote branches, and don't pursue divergent bookmarks.
  2. Add support for divergent bookmarks, but keep local tag support as well.  Add a configuration option to allow users to disable local tag support.  This option increases the complexity of the codebase and test corpus, but allows progress on the new features immediately.
  3. Create a new branch for a bookmark-based workflow, and in that branch, require Hg 2.1 or later.  Remove support for local tags in that branch.  Either hold off on publishing any release versions of this branch until the next LTS release, or maintain both this branch and a stable branch, and perform releases from both.
  4. Fork the project, and tune the fork to a clean bookmark-based workflow (maybe similar to the hgit repo?).  This allows for users to choose between Hg-Git and the fork based on their needs.  However, it splits the development.
I'm not sure which direction is best.  Thoughts on that, or anything else?

Augie Fackler

unread,
Sep 16, 2012, 9:33:28 PM9/16/12
to hg-...@googlegroups.com

On Sep 15, 2012, at 2:15 PM, David Carr <davi...@gmail.com> wrote:

> I'm not sure which direction is best. Thoughts on that, or anything else?

So, we can't (AIUI) have exactly the same behavior regarding divergent bookmarks? As long as basic use is possible on older releases, I don't care if everything works. Let's implement the most obviously hg-centric workflow, and use that as a carrot to encourage people onto the latest release.

David Carr

unread,
Sep 16, 2012, 10:56:16 PM9/16/12
to hg-...@googlegroups.com
I think that using listkeys/pushkeys to implement enhanced bookmark support will work just fine in all of our supported versions, actually.  The caveat is that the end-user workflow won't be the same between Hg versions, but that's just because the workflow with bookmarks changed between those Hg versions.  For any particular Hg version, I expect that this technique will allow the bookmark behavior to be very close (maybe identical) between remote Hg bookmarks and remote Git branches.  There may be a bit of extra work needed in the test coverage (probably skipping divergent bookmark tests for Hg < 2.1, maybe some tweaks to ensure consistent output between 2.1/2.2 and 2.3+).  Basic usage should definitely remain possible in all supported versions.

So, I think I got the feedback I need.  I'll continue working on an integration with listkeys/pushkeys, with the goal of making it possible to use Hg-Git with a totally bookmark-based workflow with modern Hg versions.  Thanks for the input, Augie.
Reply all
Reply to author
Forward
0 new messages