简体   繁体   中英

git merge work from multiple repos with no common ancestor into new repo

I have a few repos that I'd like to merge into a new master repo, and all of these repos have unique histories (absolutely no common commits among them). I've created the new master repo, created a branch on each of the other repos, and pushed each branch to the master repo. Now in master_repo, merging each branch into the master branch produces no conflicts using either git merge -s ours and also with a simple git merge (I've tried both from scratch)...but I'm failing with these attempts to merge folders from other branches into the master branch. I believe part of the problem is that there are no common ancestor commits. I can reproduce the problem as follows:

Directory structure set up within test_merge: master_repo (with folder 01) other_repoA (with folder 03) other_repoB (with folders 01 and 09)

and then in Cygwin terminal ("..." = cropped terminal messages):

$ cd master_repo/
$ git init
Initialized empty Git repository in .../test_merge/master_repo/.git/

ADDING FILE AND COMMITING ON master BRANCH OF master_repo

$ echo "text in file01" > 01/file01
$ git add *
warning: LF will be replaced by CRLF in 01/file01.
The file will have its original line endings in your working directory.
$ git commit -m "master_repo: first commit"
[master (root-commit) ...blah, blah...
1 file changed, 1 insertion(+)...blah, blah

ADDING FILE, COMMITING ON master BRANCH OF other_repoA, ADDING NEW BRANCH, AND PUSHING NEW BRANCH TO master_repo

$ cd ../other_repoA
$ git init
Initialized empty Git repository...blah,blah
$ echo "text in file03" > 03/file03
$ git add *
...
$ git commit -m "other_repoA: first commit"
...
$ git checkout -b branchA
...
$ git status
On branch branchA
nothing to commit, working directory clean
$ git push ../master_repo branchA
To ../master_repo
 * [new branch]      branchA -> branchA

ADDING FILE, COMMITING ON master BRANCH OF other_repoB, ADDING NEW BRANCH, AND PUSHING NEW BRANCH TO master_repo

$ cd ../other_repoB
$ git init
...
$ echo "text in file01 from other_repoB" > 01/file01
$ echo "text in file09 from other_repoB" > 09/file09
$ git add *
$ git commit -m "other_repoB: first commit"
...
$ git checkout -b branchB
...
$ git status
On branch branchB
nothing to commit, working directory clean
$ git push ../master_repo branchB
To ../master_repo
 * [new branch]      branchB -> branchB

A LOOK AT master_repo

$ cd ../master_repo
$ git status
On branch master
nothing to commit, working directory clean
$ git branch
  branchA
  branchB
* master
$ ls
01
$ git checkout branchA
Switched to branch 'branchA'
$ ls
03
$ git checkout branchB
Switched to branch 'branchB'
$ ls
01  09

MERGE ATTEMPT: Note that content in branches A and B seem to get ignored

$ git checkout master
Switched to branch 'master'
$ git merge -s ours branchA
$ ls
01
$ git merge -s ours branchB
Merge made by the 'ours' strategy.
$ ls
01
$ cat 01/file01
text in file01
$ git checkout branchB
Switched to branch 'branchB'
$ ls
01  09
$ cat 01/file01
text in file01 from other_repoB

The end result I wanted to see was folders 03 and 09 added to the master_repo and " from other_repoB" appended to 01/file01. Is what I'm looking for even possible using git (and NOT manually copying anything)?

You need to add some read-tree work to go with the -s ours null merge:

git merge -s ours --no-commit branchA    # null `-s ours` for `branchA` parent
git read-tree -u --prefix= branchA       # add the branchA tree at the project root
git commit

git read-tree docs

Read-tree is the core of checkout and merge and many others, anything you want to do that combines trees and index and often some worktree updates, you build this way.

I found my answer in documentation here:

https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#Other-Types-of-Merges

which explains about the -Xours option that...

all the other non-conflicting changes on that branch are merged successfully in.

as well as what -s ours does, which is a little different...

If you want to do something like this but not have Git even try to merge changes from the other side in, there is a more draconian option, which is the “ours” merge strategy. This is different from the “ours” recursive merge option.

This will basically do a fake merge. It will record a new merge commit with both branches as parents, but it will not even look at the branch you're merging in. It will simply record as the result of the merge the exact code in your current branch.

What I was looking for was the -Xours option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM