3

I’m trying to work out a method to port code between two disconnected environments using Git. Code will be edited in both locations before being merged together for releases. Ideally, I’d like to export the “master” branch from one location (A) and then add it to a repository in another location (B) as a “remote-dev” branch. After that, changes in the “remote-dev” branch can be merged into the “master” branch of the second location (B) for release preparation. This transfer would be repeated periodically so the desire is to be able to overlay “remote-dev” with updated code and have the history still preserved and still allow for merges up to “master” without having to remerge code that was previously merged. Also, only the “master” branch should be brought over from environment A as there will be many other branches with active development present that should not be copied.

The goal here is for an automated, repeatable process. I’d like to be able to setup a batch file which does the export of a branch in environment A each night. Someone will copy the files over to environment B and place them in a drop-off location. Another batch file will be scheduled to run in environment B which picks up the files and merges them into the destination repository in environment B.

There are good details in both "How do you merge two Git repositories?" and "How to import existing Git repository into another?". Unfortunately, neither seems to cover the repeatability aspect that I’m looking for.

Both discussions mention “git merge” and “git subtree add” as possible solutions here for grating a branch into a different repository. However, neither covers the repeatability aspect of it. Would it be necessary to delete the destination branch before re-merging or can the imported branch be merged over the top of a previous import? Also, should any special steps be taken to export out only the “master” branch from environment A to avoid any excess data being moved between environments?

Has anyone tried something like this with success?

StuffOfInterest
  • 488
  • 3
  • 10
  • How does this "remote-dev" branch you're talking about differ from git's remote-tracking branches? I may be missing something, but it looks to me like you're describing standard git operating procedure. You're not restricted to a single remote, all repositories (you're calling them "environment"s) are peers even though they're often most conveniently treated as a hierarchy. – jthill Apr 05 '18 at 14:38
  • These environments are completely separate networks that are unable to directly interact with each other. Any files being taken from one to the other have to be manually copied over with portable media. – StuffOfInterest Apr 05 '18 at 15:17
  • Use [`git bundle`](https://git-scm.com/docs/git-bundle) for sneakernet transport, the first sentence of its description is "Some workflows require that one or more branches of development on one machine be replicated on another machine, but the two machines cannot be directly connected, and therefore the interactive Git protocols (git, ssh, http) cannot be used." – jthill Apr 05 '18 at 16:21
  • p.s. while my question belonged where it is, the rest of my responses above is best read as commentary on Mark Adelsberger's on-target answer. I think you're just wanting to use git as it's meant to be used, and the need for a sneakernet is rare enough that you hadn't run across any pointers to `git bundle` before. – jthill Apr 05 '18 at 16:27

1 Answers1

3

You describe the environments as "disconnected". I assume you mean that you cannot add one repo as a remote of the other. The solution for that is to use git bundle.

At repo 1, you create a bundle file. You will specify that you want the bundle created from masters history.

If you want, you can also make the bundles incremental by specifying a "starting point" for the bundle. By this I mean, you can say "if you're going to import this bundle, you must already have commit ABC, because that's the parent commit of the first commit in the bundle".

On the receiving end, you add the bundle file as though it were a remote, and then you can fetch from it and merge the resulting refs, or pull from it, or whatever. Just like a remote. The only thing is you don't push to the bundle. Instead you create your own bundle to send back.

So that removes the "disconnected" aspect from the picture.

If you want to bundle up master and then have it received as remote-dev, you could use a refspec when you fetch from the bundle; or you could go ahead and fetch it as remote-dev/master and then track that with a local branch called rmeote-dev; or any number of other variations.

It's repeatable whether or not you make the bundles incremental, because fetch always knows that it might already have some of the objects in the history it's fetching.

So now you're just syncing between two long-lived branches, much like the pattern you'd use to take periodic vendor drops or update a fork from its upstream.


As an aside, the above answer assumes you have reasons, apart from the disconnected environment, for wanting the branch workflow you described. The truth is, with bundle files you can work pretty much the same as you would with connected repositories, so if you were assuming the need for a remote-dev branch just to deal with the separation, I wouldn't bother. Distributed development is exactly what git is for.

Mark Adelsberger
  • 32,904
  • 2
  • 24
  • 41
  • "git bundle" was definitely the winner. Teamed it up with "git fetch" on the receiving end. Sending: "git bundle create file.bundle master" Receiving: "git fetch file.bundle master:remotedev". Still working on my scripts for automating the processes but I've been able to test where I did multiple exports and imports along with data changes along with edits on both sides between updates of the repository. – StuffOfInterest Apr 09 '18 at 16:21