Using git to combine two directories with a common parent (but with a different SHA1)

In our project, someone took a copy of the code. They started a new git repository in their directory and continued their work there. In the meantime, work continued on our main project repository. Now we are left with two git repositories without a shared SHA1.

A --- B --- C --- D | | Copy of code to new directory | E --- F --- G 

B and E are the same files, folders, etc.

Our goal is to use git to merge the changes of F and G into the main branch (currently in D)

+4
source share
2 answers

First, I'm going to redraw the chart.

  A --- B --- C --- D master

          E --- F --- G copy

First put both of them in the same repo. There are no special steps for this, you just git fetch both in the same repository.

Then you create a transplant. Edit .git/info/grafts ...

 <E-sha1> <B-sha1> 

Then run git filter-branch to make it persistent.

 git filter-branch --tag-name-filter cat -- --all 

This will create a new story, a β€œcorrect” story:

  A --- B --- C --- D master
         \
          E --- F --- G copy

After that you can just drain.

Demo in action

I created two repositories that corresponded to the chart, copying from commit B to make commit E.

  • E has SHA-1 3aa6b69127d20ac42746c39be3c273a9d80fb706
  • B has SHA-1 95b0fc836dbea7eaa0d043390df841d184af7cd5
  $ git init
 $ git remote add master ../gittest
 $ git remote add copy ../gittest2
 $ git fetch master
 remote: Counting objects: 12, done.
 remote: Compressing objects: 100% (7/7), done.
 remote: Total 12 (delta 2), reused 0 (delta 0)
 Unpacking objects: 100% (12/12), done.
 From ../gittest
  * [new branch] master -> master / master
 $ git checkout -b master master / master
 Branch master set up to track remote branch master from master.
 Already on 'master'
 $ git fetch copy
 warning: no common commits
 remote: Counting objects: 9, done.
 remote: Compressing objects: 100% (6/6), done.
 remote: Total 9 (delta 0), reused 0 (delta 0)
 Unpacking objects: 100% (9/9), done.
 From ../gittest2
  * [new branch] master -> copy / master
 $ git log --format = oneline copy / master |  tail -n 1
 3aa6b69127d20ac42746c39be3c273a9d80fb706 E
 $ git log --format = oneline master / master
 1532332fe705931babe9db04c8d84051867b52c9 D
 90903c0ac8dc26649b875ee00ea39bfd7571b1fb C
 95b0fc836dbea7eaa0d043390df841d184af7cd5 B
 e9de90c82a32041cff3a19f8e40d4358bc4ec2ca Commit A
 $ git log --format = oneline master / master
 bec0e7af9374e4c57cb87f3fd5b2fb2b6a3f431b G
 a61e01d096e81c36bcc450afd98ca94cff909622 F
 3aa6b69127d20ac42746c39be3c273a9d80fb706 E

What happens if you merge now?

I had merge conflicts that I would prefer to auto-negotiate.

  $ git merge copy / master
 Auto-merging test.txt
 CONFLICT (add / add): Merge conflict in test.txt
 Automatic merge failed;  fix conflicts and then commit the result.

Vaccinations in action

  $ echo 3aa6b69127d20ac42746c39be3c273a9d80fb706 \ 
      95b0fc836dbea7eaa0d043390df841d184af7cd5> .git / info / grafts
 $ git filter-branch --tag-name-filter cat - --all
 Rewrite bec0e7af9374e4c57cb87f3fd5b2fb2b6a3f431b (7/7)
 WARNING: Ref 'refs / heads / master' is unchanged
 Ref 'refs / remotes / copy / master' was rewritten
 WARNING: Ref 'refs / remotes / master / master' is unchanged
 $ git merge copy / master
 Auto-merging test.txt
 Merge made by the 'recursive' strategy.
  test.txt |  5 +++++
  1 file changed, 5 insertions (+)

Final result

  $ git log --graph --oneline |  cat
 * 4dadb0a Merge remote-tracking branch 'copy / master'
 | \ |  
 |  * bb2fc85 G
 |  * be88bc5 F
 |  * 0816baf E
 * |  1532332 D
 * |  90903c0 C
 | /  
 * 95b0fc8 B
 * e9de90c Commit A
+7
source

Suppose you are in a repo right now, turn on A---B---C---D

You need to first add another repo to this repo using the command.

 $git remote add another_repo <git repo path> $git fetch another_repo 

Then you can combine, use

 $git merge another_repo/master 
0
source

All Articles