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

In our project somebody took a copy of the code. They started a new git repository in their directory and continued their work there. Meanwhile the work on our main project repository also continued. We are now left with two git repositories with no common SHA1.

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

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

  • Should initial Git commit contain auto generated files?
  • Git Extensions + Git For Windows: Fetching Branch that does not exist Locally does not Create New Local Branch
  • setting up github ssh on windows 7 machine
  • Development environment with multiple developers on a single application
  • Azure deploy from several repositories in one website
  • Travis-CI: deploy different branches to different servers
  • Our goal is to use Git to merge changes F and G into the main branch (currently at D)

  • File Could not be edited Github pages
  • What happened to this git commit? Issue with “untracked files”
  • How to diagnose and fix git fatal: unable to read tree
  • Git submodule update from post-receive hook
  • Creating classes for using Document Conversion and Concept Insights in Java
  • Git remove file from all commits
  • 2 Solutions collect form web for “Using git to merge two directories with common parent (but different SHA1)”

    First, I’m going to redraw your diagram.

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

    Let’s first put both of these in the same repo. There are no special steps to this, you just git fetch both into the same repository.

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

    <E-sha1> <B-sha1>
    

    Then run git filter-branch to make it permanent.

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

    This will create a new history, the “correct” history:

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

    After that, you can just merge.

    Demo in action

    I created two repositories which matched the diagram, 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 got merge conflicts that I’d rather auto-resolve.

    $ 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.
    

    Grafts 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(+)
    

    The 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
    

    Assume you are now in the repo include A---B---C---D.

    You need first to add the other repo into this repo use the command.

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

    Then you can merge, use

    $git merge another_repo/master
    
    Git Baby is a git and github fan, let's start git clone.