하위 디렉토리에 git 저장소 병합
내 작업 git 저장소의 원격 git 저장소를 하위 디렉토리로 병합하고 싶습니다. 결과 저장소에 두 저장소의 병합 된 기록이 포함되고 병합 된 저장소의 각 파일이 원격 저장소에있는 것처럼 기록이 유지되기를 원합니다. How to use the subtree merge strategy 에서 언급 한대로 하위 트리 전략을 사용해 보았지만 해당 절차를 수행 한 후 결과 저장소에는 실제로 두 저장소의 병합 된 기록이 포함되어 있지만 원격 저장소에서 오는 개별 파일은 해당 기록을 유지하지 않습니다. ( 'git log'중 하나에 "Merged branch ..."라는 메시지 만 표시됩니다.)
또한 두 개의 결합 된 git 저장소가 더 이상 분리되는 것을 원하지 않기 때문에 하위 모듈을 사용하고 싶지 않습니다.
원격 저장소에서 가져온 개별 파일이 기록을 유지하는 하위 디렉토리로 다른 저장소의 원격 git 저장소를 병합 할 수 있습니까?
도움을 주셔서 대단히 감사합니다.
편집 : 현재 git filter-branch를 사용하여 병합 된 저장소 기록을 다시 쓰는 솔루션을 시도하고 있습니다. 작동하는 것 같지만 좀 더 테스트해야합니다. 나는 내 결과를보고하기 위해 돌아갈 것이다.
편집 2 : 원격 저장소의 파일 기록이 명백하게 손실되는 결과로 git의 하위 트리 전략과 함께 사용한 정확한 명령을 더 명확하게 제공하기를 바랍니다. A를 현재 작업중인 git repo로하고 B를 A에 하위 디렉토리로 통합하려는 git repo를 지정합니다. 다음을 수행했습니다.
git remote add -f B <url-of-B>
git merge -s ours --no-commit B/master
git read-tree --prefix=subdir/Iwant/to/put/B/in/ -u B/master
git commit -m "Merge B as subdirectory in subdir/Iwant/to/put/B/in."
이 명령을 실행하고 subdir / Iwant / to / put / B / in 디렉토리로 이동하면 B의 모든 파일이 표시되지만 git log
그중 하나에 "Merge B as subdir in subdir / Iwant / to / put /큰 상자." B에있는 파일 기록은 손실됩니다.
어떤 것 (나는 자식에 초보자이야 이후 내가 잘못 될 수있다) 작업으로 다음과 같다 :
git remote add -f B <url-of-B>
git checkout -b B_branch B/master # make a local branch following B's master
git filter-branch --index-filter \
'git ls-files -s | sed "s-\t\"*-&subdir/Iwant/to/put/B/in/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
git checkout master
git merge B_branch
filter-branch에 대한 위의 명령은에서 가져 왔습니다 git help filter-branch
. 여기서 저는 subdir 경로 만 변경했습니다.
무슨 일이 일어나고 있는지에 대한 자세한 설명을 얻은 후에 나는 그것을 이해한다고 생각하며 어떤 경우에도 해결 방법이 있습니다. 특히, 나는 이름 변경 감지가 --prefix와의 하위 트리 병합에 속고 있다고 생각합니다. 내 테스트 사례는 다음과 같습니다.
mkdir -p z/a z/b
cd z/a
git init
echo A>A
git add A
git commit -m A
echo AA>>A
git commit -a -m AA
cd ../b
git init
echo B>B
git add B
git commit -m B
echo BB>>B
git commit -a -m BB
cd ../a
git remote add -f B ../b
git merge -s ours --no-commit B/master
git read-tree --prefix=bdir -u B/master
git commit -m "subtree merge B into bdir"
cd bdir
echo BBB>>B
git commit -a -m BBB
우리는 각각 여러 커밋으로 git 디렉토리 a와 b를 만듭니다. 하위 트리 병합을 수행 한 다음 새 하위 트리에서 최종 커밋을 수행합니다.
달리기 gitk
(z / a)는 히스토리가 나타나는 것을 보여줍니다. 우리는 그것을 볼 수 있습니다. 달리기 git log
는 역사가 나타나는 것을 보여줍니다. 그러나 특정 파일을 보면 문제가 있습니다.git log bdir/B
음, 우리가 할 수있는 트릭이 있습니다. --follow를 사용하여 특정 파일의 이름 바꾸기 이전 기록을 볼 수 있습니다. git log --follow -- B
. 이것은 좋지만 사전 병합의 기록을 병합 후의 기록과 연결하지 못하기 때문에 좋지 않습니다.
-M과 -C를 가지고 놀았지만 특정 파일을 따라갈 수 없었습니다.
그래서 해결책은 git에게 하위 트리 병합의 일부로 발생하는 이름 변경에 대해 알려주는 것입니다. 불행히도 git-read-tree는 하위 트리 병합에 대해 매우 까다롭기 때문에 임시 디렉토리를 통해 작업해야하지만 커밋하기 전에 사라질 수 있습니다. 그 후 우리는 전체 역사를 볼 수 있습니다.
먼저 "A"저장소를 만들고 몇 가지 커밋을 만듭니다.
mkdir -p z/a z/b
cd z/a
git init
echo A>A
git add A
git commit -m A
echo AA>>A
git commit -a -m AA
둘째, "B"저장소를 만들고 몇 가지 커밋을 만듭니다.
cd ../b
git init
echo B>B
git add B
git commit -m B
echo BB>>B
git commit -a -m BB
그리고이 작업을 수행하는 비결은 Git이 하위 디렉토리를 만들고 내용을 이동하여 이름을 인식하도록 강제합니다.
mkdir bdir
git mv B bdir
git commit -a -m bdir-rename
저장소 "A"로 돌아가서 "B"의 내용을 가져와 병합합니다.
cd ../a
git remote add -f B ../b
git merge -s ours --no-commit B/master
# According to Alex Brown and pjvandehaar, newer versions of git need --allow-unrelated-histories
# git merge -s ours --allow-unrelated-histories --no-commit B/master
git read-tree --prefix= -u B/master
git commit -m "subtree merge B into bdir"
이제 병합되었음을 표시하려면 :
cd bdir
echo BBB>>B
git commit -a -m BBB
전체 역사가 연결된 체인에 보존되어 있음을 증명하려면 :
git log --follow B
We get the history after doing this, but the problem is that if you are actually keeping the old "b" repo around and occasionally merging from it (say it is actually a third party separately maintained repo) you are in trouble since that third party will not have done the rename. You must try to merge new changes into your version of b with the rename and I fear that will not go smoothly. But if b is going away, you win.
git-subtree
is a script designed for exactly this use case of merging multiple repositories into one while preserving history (and/or splitting history of subtrees, though that is seems to be irrelevant to this question). It is distributed as part of the git tree since release 1.7.11.
To merge a repository <repo>
at revision <rev>
as subdirectory <prefix>
, use git subtree add
as follows:
git subtree add -P <prefix> <repo> <rev>
git-subtree implements the subtree merge strategy in a more user friendly manner.
If you are really wanting to stitch things together, look up grafting. You should also be using git rebase --preserve-merges --onto
. There is also an option to keep the author date for the committer information.
I wanted to
- keep a linear history without explicit merge, and
- make it look like the files of the merged repository had always existed in the subdirectory, and as a side effect make
git log -- file
work without--follow
.
Step 1: Rewrite history in the source repository to make it look like all files always existed below the subdirectory.
Create a temporary branch for the rewritten history.
git checkout -b tmp_subdir
Then use git filter-branch
as described in How can I rewrite history so that all files, except the ones I already moved, are in a subdirectory?:
git filter-branch --prune-empty --tree-filter '
if [ ! -e foo/bar ]; then
mkdir -p foo/bar
git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files foo/bar
fi'
Step 2: Switch to the target repository. Add the source repository as remote in the target repository and fetch its contents.
git remote add sourcerepo .../path/to/sourcerepo
git fetch sourcerepo
Step 3: Use merge --onto
to add the commits of the rewritten source repository on top of the target repository.
git rebase --preserve-merges --onto master --root sourcerepo/tmp_subdir
You can check the log to see that this really got you what you wanted.
git log --stat
Step 4: After the rebase you’re in “detached HEAD” state. You can fast-forward master to the new head.
git checkout -b tmp_merged
git checkout master
git merge tmp_merged
git branch -d tmp_merged
Step 5: Finally some cleanup: Remove the temporary remote.
git remote rm sourcerepo
Have you tried adding the extra repository as a git submodule? It won't merge the history with the containing repository, in fact, it will be an independent repository.
I mention it, because you haven't.
I found the following solution workable for me. First I go into project B, create a new branch in which already all files will be moved to the new sub directory. I then push this new branch to origin. Next I go to project A, add and fetch the remote of B, then I checkout the moved branch, I go back into master and merge:
# in local copy of project B
git checkout -b prepare_move
mkdir subdir
git mv <files_to_move> subdir/
git commit -m 'move files to subdir'
git push origin prepare_move
# in local copy of project A
git remote add -f B_origin <remote-url>
git checkout -b from_B B_origin/prepare_move
git checkout master
git merge from_B
If I go to sub directory subdir
, I can use git log --follow
and still have the history.
I'm not a git expert, so I cannot comment whether this is a particularly good solution or if it has caveats, but so far it seems all fine.
참고URL : https://stackoverflow.com/questions/6426247/merge-git-repository-in-subdirectory
'programing tip' 카테고리의 다른 글
오류를 제공하는 Windows의 pip-알 수 없거나 지원되지 않는 명령 'install' (0) | 2020.11.03 |
---|---|
.NET Framework 디렉터리 경로 가져 오기 (0) | 2020.11.03 |
Git Bash와 Windows 용 GitHub 쉘의 차이점은 무엇입니까? (0) | 2020.11.02 |
푸시는 새로운 원격 헤드를 만듭니다! (0) | 2020.11.02 |
배열을 트리밍 할 수없는 이유는 무엇입니까? (0) | 2020.11.02 |