Skip to content

Instantly share code, notes, and snippets.

@kuri65536
Last active September 16, 2018 22:41
Show Gist options
  • Save kuri65536/67cf6ce9413beb941a98e69660f66a66 to your computer and use it in GitHub Desktop.
Save kuri65536/67cf6ce9413beb941a98e69660f66a66 to your computer and use it in GitHub Desktop.
git append the unrelated repo onto your repo

git append the unrelated repo onto your repo

  • repo-A have revisions: A-1 -> A-2
  • repo-B have revisions: B-1 -> B-2

goal

in repo-B

A-1 -> A-2 -> (buffer revision) -> B-1 -> B-2

full command

confirm revision

$ cd repo-A
$ git tag --pretty=oneline
9a76d3c0f6d7305c138102855aadc5dfaa36551a (HEAD -> master) commit A-2   # rev. is the base to add on.
3101c25d6c5aa362e3fa2320e2ea04be23ca8063 commit A-1

let combine repo-B after repo-A's commit A-2.

let's do it

$ cd repo-B
$ git checkout --orphan tmp
$ mkdir proj-B
$ touch proj-B/.gitkeep
$ git add proj-B
$ git commit proj-B -m 'move contents to sub-directory'
$ git checkout master
$ git rebase tmp
$ git filter-branch --tree-filter 'mv * ./proj-B; git mv -k * ./proj-B' HEAD
$ git branch -D tmp
$ git checkout --orphan tmp
$ cp --rdpv ../repo-A/* .
$ git add README.md  # register the contents, except of proj-B
$ git commit README.md -m 'ignore repo-A contents'
$ git checkout master
$ git rebase tmp
$ git branch -D tmp
$ git log --pretty=oneline
396d4a0a97425085118e28c99764c84df462e755 (HEAD -> master) commit B-2
...
472ec6493f6b0b13fdd9ea1543c277db16bb8439 ignore repo-A contents  # rev. is start to add on

$ echo '472ec6493f6b0b13fdd9ea1543c277db16bb8439 9a76d3c0f6d7305c138102855aadc5dfaa36551a' > .git/info/grafts
$ git fetch ../repo-A
$ git filter-branch -f
$ git log --pretty=oneline
0e019996bbf9dfe408f8bbfb79e33fd8c57d69c5 (HEAD -> master) commit B-2
973af94f3c1ef1a4435f50879da025f87584ca9d commit B-1
5c0e049ee9be4757afb802efa06a8c68f4ebc90d move contents to sub-directory
6055936f7a2d74a6c3eec1417dcb5f768a73475b ignore repo-A contents
9a76d3c0f6d7305c138102855aadc5dfaa36551a commit A-2
3101c25d6c5aa362e3fa2320e2ea04be23ca8063 commit A-1

# x git push ../repo-A master   # you can't do this...
$ cd ../repo-A
$ git pull ../repo-B  # you can do it.

Explains for the command

Make sub-directory for proj-B

In my case, I want to put proj-B in sub-directory to prevent the conflict files with proj-A. So we dig the sub-direcotry in repo-B.

$ cd repo-B
$ git checkout --orphan tmp
$ mkdir proj-B
$ touch proj-B/.gitkeep

Rebase

Put this buffer rebision at base of repo-B.

$ git add proj-B
$ git commit proj-B -m 'move contents to sub-directory'
$ git checkout master
$ git rebase tmp

Modify revisions

Below commands modify the all repo-B works under sub-directory.

$ git filter-branch --tree-filter 'mv * ./proj-B; git mv -k * ./proj-B' HEAD
$ git branch -D tmp

Register repo-A contents for merge

This prevent the deleting repo-A contents at merging. Please be aware to add all of repo-A files in git add. (In this case, repo-A has only one contents README.md)

$ git checkout --orphan tmp
$ cp --rdpv ../repo-A/* .
$ git add README.md  # register the contents, except of proj-B
$ git commit README.md -m 'ignore repo-A contents'

Rebase

Put this buffer rebision at base of repo-B.

$ git checkout master
$ git rebase tmp

Confirm revisions

At now, repo-B is ready for merge.

$ git branch -D tmp
$ git log --pretty=oneline
396d4a0a97425085118e28c99764c84df462e755 (HEAD -> master) commit B-2
...
472ec6493f6b0b13fdd9ea1543c277db16bb8439 ignore repo-A contents  # rev. is start to add on

Setup for graft

We can tell revision relationship to git by below command.

$ echo '472ec6493f6b0b13fdd9ea1543c277db16bb8439 9a76d3c0f6d7305c138102855aadc5dfaa36551a' > .git/info/grafts

Graft and confirm

$ git fetch ../repo-A
$ git filter-branch -f
$ git log --pretty=oneline
0e019996bbf9dfe408f8bbfb79e33fd8c57d69c5 (HEAD -> master) commit B-2
973af94f3c1ef1a4435f50879da025f87584ca9d commit B-1
5c0e049ee9be4757afb802efa06a8c68f4ebc90d move contents to sub-directory
6055936f7a2d74a6c3eec1417dcb5f768a73475b ignore repo-A contents
9a76d3c0f6d7305c138102855aadc5dfaa36551a commit A-2
3101c25d6c5aa362e3fa2320e2ea04be23ca8063 commit A-1
  • Pros) repo-A revisions didnot changed.
  • Cons) buffer revisions are not meaningful.

if you want to repo-B revision to be no-change, skip the steps make sub-directory, and then move sub-direcotry in new merged repo. (you can do when repo-B and repo-A are no-conflict.)

Push back to repo-A or github

# x git push ../repo-A master   # you can't do this...
$ cd ../repo-A
$ git pull ../repo-B  # you can do it.

prepare test data

repo-A

$ git init repo-A
$ cd repo-A
$ echo this is repo-A > README.md
$ git add README.md
$ git commit -m 'commit A-1'
$ echo append in A-2 >> README.md
$ git commit -a -m 'commit A-2'

repo-B

$ cd ..  # if your are in repo-A
$ git init repo-B
$ cd repo-B
$ echo this is repo-B > README.md
$ git add README.md
$ git commit -m 'commit B-1'
$ echo append in B-2 >> README.md
$ git commit -a -m 'commit B-2'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment