1

This is currently a purely theoretical question (related to this one), but let me first give the background. Whenever you run hg gexport the initial hash will vary from invocation to invocation. This is similar to when you run git init or hg init. However, since the Mercurial and Git commits correspond to each other and build on previous hashes, there should be some way to start over from a minimal common initial state (or minimal state on the Git side, for example).

Suppose I have used hg-git in the past and now I am trying to sync again between my Mercurial and my Git states, but without (or very little of) the original .git directory from the hg gexport. What I do have, though, are the two metadata files: git-mapfile and git-tags.

There is an old Git mirror, which is sort of "behind" and the Mercurial repo which is up-to-date.

Then I configure the Mercurial repo for hg-git like so (.hg/hgrc):

[git]
intree = True

[extensions]
hgext.bookmarks=
topic=
hggit=

[paths]
default = ssh://username@hgserver.tld//project/repo
gitmirror = git+ssh://username@server.tld/project/repo.git

If I now do the naive hg pull gitmirror all I will gain is a duplication of every existing commit on an unrelated branch with unrelated commit history (and the double amount of heads, compared to prior to the pull).

It clearly makes no big difference to place those two metadata files (git-mapfile and git-tags) into .hg. The biggest difference is that the pull without these files will succeed (but duplicate everything) and the pull with them will error out at the first revision because of "abort: unknown revision ..." (even makes sense).

Question: which part(s) and how much (i.e. what's the minimum!) of the Git-side data/metadata created by hg gexport do I have to keep around in order to start over syncing with hg-git? (I was unable to find this covered in the documentation.)

0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
  • On the rights on delirium: why you do not want to start from scratch and in (somehow) more natural way? If you have local clone of mercurial-repo, just push it to new empty git-repo without any additional tricks like `hg gexport`? I **use** hg-git this way at least some years – Lazy Badger Jan 23 '22 at 12:51
  • `/.hg/git` or `/.git` (in your case) is **full-fledged git-repository**, you can't restore it from none to full with just *some files*, I'm afraid – Lazy Badger Jan 23 '22 at 12:56
  • @LazyBadger because others may have cloned the Git mirror, so starting over is about as rude (or depending on the vantage point: wrong) as would a force push on a public Git repo. I was asking for the minimum required. I think I even demonstrate in my question that "from none" won't work. – 0xC0000022L Jan 23 '22 at 13:23
  • Could you start from the current git repo; then run hg-git separately. Merge the "foreign" hggit repo into the git one; and then "graft" (or whatever the git equivalent is) only the new / relevant changes, and discard the rest? – StayOnTarget Jan 24 '22 at 13:09

1 Answers1

2

The core metadata is stored in .hg/git-mapfile, and the actual Git repository is stored in .hg/git or .git dependending on intree. The git-mapfile is the only file needed to reproduce the full state; anything else is just cache. In order to recreate a repository from scratch, do the following:

  1. Clone or initialise the Mercurial repository, somehow.
  2. Clone or initialise the embedded Git repository, e.g. using git clone --bare git+ssh://username@server.tld/project/repo.git .hg/git.
  3. Copy over the metadata from the original repository, and put it into .hg/git-mapfile.
  4. Run hg git-cleanup to remove any commits from the map no longer known to Mercurial.
  5. Pull from Git.
  6. Push to Git.

These are the steps I'd use, off the top of my head. The three last steps are the most important. In particular, you must pull from Git to populate the repository prior to pushing; otherwise, the conversion will fail.

  • I just verified your instructions and they are spot on. The only change, but you mentioned that, was the `intree` setting in my case. The one thing I will need verify now is, if it is possible to strip everything on the Git side up to the very first commit and use the Hg side to restore the Git repo from scratch. At least that would be my idea. Since subsequent commits should be based on previous ones, I would hope that that works. Then what I need to keep is a (Git) bundle of the first commit and a full Hg bundle and `git-mapfile`. – 0xC0000022L Feb 15 '23 at 23:06