Combining Unrelated Git Repositories: When Projects Collide! | by Sebastian Royer | May, 2022

How do you merge two Git repositories?

When worlds collide!

Lately began a challenge to construct an AI-powered bookmarking extension for Chrome utilizing separate git repositories to get the heart created: one for the chrome extension and one for a React/TypeScript front-end.

I figured it will be easier to begin with remoted repositories and mix them as soon as I had primary performance working for every half. Finally I wanted to mix these repositories to be able to use the front-end for the popup and Bookmark page override within the chrome extension.

I went google searching and located this concise and nicely voted reply on learn how to merge one repository into one other:

It’s positively price studying and is by definition the TLDR for this text.

After digging by the feedback there I made a decision to go line by line by the beneficial method and examine it towards the git documentation to be able to higher perceive what was occurring beneath “the porcelain” as they are saying. Fortunate for you, I took notes.

For reference right here is the top-voted and accepted answer to merge project-a into project-b, with line numbers that hyperlink to the reasons under:

1 cd path/to/project-b
2 git distant add project-a /path/to/project-a
3 git fetch project-a --tags
4 git merge --allow-unrelated-histories project-a/grasp # or whichever department you need to merge
5 git distant take away project-a

We begin simply sufficient:

1 cd path/to/project-b

The cd command adjustments your working listing to project-b in order that we are able to merge project-a into it. Easy 🙂

2 git distant add project-a /path/to/project-a

The git distant command ‘manages the set of repositories (“remotes”) whose branches are tracked’ and we’ll be utilizing it once more later as nicely.
git distant add provides the named distant repository from the desired path or url. So right here we’re including project-a as a distant repository to the project-b repository from the placement /path/to/project-a.

3 git fetch project-a --tags 

git fetch ‘downloads objects and refs from one other repository’.
fetch downloads branches and tags (collectively, ‘refs’) from the repositories named together with the objects obligatory to finish their histories. Any tag that factors into the referenced histories can be fetched.
Utilizing the--tags possibility fetches all tags from the distant ‘refs/tags/’ listing into the native repository’s tags with the identical title.
As these initiatives are each fairly younger and I’ve not begun to model them I would not have any tags of worth to mix, so I’m not going to incorporate the — tags flag in my command.

For a bit extra depth on tags confer with my diversion below.

4 git merge --allow-unrelated-histories project-a/grasp # or whichever department you need to merge 

Right here we get to the meat of the method with git merge which ‘joins two or extra improvement histories collectively.

The merge command incorporates adjustments from the named commit(s) into the present department. It can ‘replay’ the commit adjustments made on the named commit’s department because it diverged from the present department and file the end in a brand new commit together with the names of the two-parent commits and a log message from the person. As you may already know, this can be a widespread state of affairs with a number of branches in a single repository and that’s the method the merge command is usually designed and used. It does this by evaluating the state of the recordsdata within the named commit’s department to the identical recordsdata’ state within the present department and utilizing a diffing algorithm to search out the place they diverge. Non-overlapping adjustments are made mechanically whereas overlapping adjustments or ‘conflicts’ are offered to the person to pick which model of the road to make use of.

Somewhat than dig too deep on the underlying mechanics I’ll simply level to this simple answer as a very good introduction to the three-way-merge algorithm that git defaults to, a very good overview of the different merge strategies, and Atlassian’s worthy tutorial entry.

In our case we aren’t merging branches with a shared historical past, so the --allow-unrelated-histories flag explicitly lets us merge two histories that would not have a typical ancestor. If these had been completely different variations of the identical challenge this could be a doubtlessly catastrophic operation that might depart our working tree lacking commits with no solution to revert, which is why the flag was launched. With two separate initiatives mixed, nonetheless, these points will not be doable.

For the really adventurous, right here is the actual implementation of git merge the place a fast Discover in Web page with the string ‘allow_unrelated’ will traverse within the code to the place the--allow-unrelated-histories flag is dealt with.

An vital observe picked up from the docs is to verify to have your working tree updated with all adjustments on each the named and present branches (or in our case repositories,) with no excellent unstaged adjustments that you just may care about. If this isn’t the case these excellent adjustments have an opportunity of being misplaced.

5 git distant take away project-a

Lastly, we return to git distant and use git distant take away to take away the named project-a from project-b’s distant monitoring. All remote-tracking branches and configuration settings for project-a are faraway from project-b, in order that our now merged challenge now not refers back to the nonetheless present project-a. This completes our course of by uncoupling the 2 repositories after we’ve got integrated project-a‘s recordsdata and historical past into project-b efficiently.

Not included within the unique stackoverflow.com reply we may embody a line like rm -rf path/to/project-a if we now not needed to maintain the copy of the unique project-a.

I wound up cleansing up each initiatives’ working bushes after which ran these actual instructions to merge my two initiatives. It went as easily as marketed within the reply feedback, with just one line of battle in my .gitignore file which was simply mounted. Should you’ve learn this far, I hope you’ve obtained a few repos to smash collectively! Good luck!

Right here I felt the necessity to replace myself on the tag performance in git. As soon as once more, the superb git docs lay it out.

Basically tags in git can be utilized to create a label for a selected commit, permitting you to reference it later. They permit a canonical reference level to a particular commit versus a department that begins at a particular commit after which tracks with adjustments. This enables for, specifically, versioning notation, so {that a} particular commit will be labeled as eg. v1.4 and later referenced through git instructions.

There are two kinds of tags: ‘light-weight’ and ‘annotated’.

Light-weight shops solely the tag title and reference to the commit checksum. It may be used to retailer non permanent tags as a reference to transitional states or usually tags that aren’t anticipated to be maintained/shared.

Annotated tags embody a message in addition to a tag title, and retailer a full checksummed object within the git database together with the tagger’s data and tagging date. That is the beneficial kind of tag for many tagging because it offers full data and will be signed and verified with GPG if wanted.

A pleasant function is the power to tag commits after the very fact in order that the labeling course of within the case of versioning doesn’t should happen in real-time however will be managed individually.

Tags will not be shared by default when utilizing i.e. git push to a distant, so similar to our git fetch --tags name a git push --tags possibility exists to ship tags to a distant repository if desired.

More Posts