Dmitry Leskov
 

Git Tip: Quickly Merging in a Side Project Repo

The code of the filter in my older post about EAC and UTF-8 entries in freedb has evolved into a small helper utility for another project. At some point I decided to merge the Git repo containing that helper into the repo of that new project. The collective wisdom of the Internet says to use submodules or subtree merges in such a situation, but I have found a less complicated solution that worked for me (Credit goes to Dave O’Neil.)

Specifically, if you only want to retain the history of the master branch of the secondary repo, simply fetch that branch under a different name into the main project repo, and then merge it as you would merge a normal branch:

  1. Make sure the secondary repo is in good state – no postponed merges or uncommitted changes to the master branch.
  2. Make sure no untracked files in the working directory of the primary repo are conflicting with files in the secondary repo. Having e.g. a README in the root of both repos is okay, provided you do not skip the optional step below.
  3. Create a backup of the primary repo. You may also wish to try the below steps on a temporary clone first:

    git clone main-project-url temp-clone-directory
  4. Fetch the master branch from the secondary repo into the main project:

    cd main-project-directory
    git fetch secondary-repo-url master:subproject

    Now in the current repository there is a branch subproject that contains the master branch of the secondary-repo.

  5. (Optional) If required, checkout that branch and move files to an appropriate location to avoid conflicts:

    git checkout -f subproject
    mkdir subproject-directory
    git mv subproject-files subproject-directory
    git commit -a -m "Moved subproject to a separate directory before merge"
    git checkout -f master
  6. Now merge the subproject branch into the master branch:

    git merge subproject

    If you get a merge conflict message, you must have skipped the previous step. Ensure that files of the secondary project reside in a separate directory not present in the primary project.

Now the history of the master branch of your subproject is part of history of the main project as if you had been working on it in a separate branch called subproject.

Here is a small script illustrating the process:

#!/bin/bash
[ -d primary ] && rm -fr primary
[ -d secondary ] && rm -fr secondary 
mkdir primary
mkdir secondary

cd primary
git init
echo Primary >README
git add .
git commit -a -m 'Initial commit to primary'
cd ..

cd secondary 
git init
echo Secondary >README
git add .
git commit -a -m "Initial commit to secondary"
cd ..

cd primary
git fetch ../secondary master:secondary
git checkout secondary
mkdir secondary
git mv README secondary
git commit -a -m "Moved secondary to a separate directory before merge"
git checkout -f master

git merge secondary
git log --graph

As you may see, the script creates two subdirectories – primary and secondary, initializes a git repo in each of them, commits README files to those repos, and fetches the master branch from the secondary repo into the primary one under the name “secondary“. A merge attempt at this point would result in a conflict because both branches contain a file README in their roots. So the script moves the fetched file into a new subdirectory before the merge.

Here is how the log of the primary project looks in TortoiseGit now:

TortoiseGit screenshot

Tags:

« | »

Talkback

* Copy This Password *

* Type Or Paste Password Here *