在子目录中合并git存储库 [英] Merge git repository in subdirectory

查看:106
本文介绍了在子目录中合并git存储库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将我的工作git存储库中的远程git存储库合并为其子目录。我希望生成的存储库包含两个存储库的合并历史记录,并且合并到的存储库的每个文件都保留其在远程存储库中的历史记录。我尝试使用中提到的子树策略如何使用子树合并策略,但遵循该过程后,尽管生成的存储库确实包含两个存储库的合并历史记录,但来自远程文件的单个文件并未保留其历史记录(`git log'他们中的任何一个都只显示一条消息Merged branch ...)。

另外我不想使用子模块,因为我不想要两个组合的git



是否有可能将另一个远程git存储库合并为子目录,并将远程存储库中的单个文件保留其历史记录 p>

非常感谢您的帮助。

编辑:
我目前正在尝试一个解决方案使用git filter-branch重写合并版本库历史记录。它似乎工作,但我需要再测试一下。我会回来报告我的调查结果。

编辑2:
希望我能更清楚地说明我使用的是git的子树策略,这导致远程存储库的文件的历史明显丢失。
让A是我目前工作的git repo,B是git repo,我想将它作为子目录并入到A中。它做了以下工作:

  git remote add -f B  
git merge -s our -no-commit B / master
git read-tree --prefix = subdir / Iwant / to / put / B / in / -u B / master
git commit -m将B合并为subdir / Iwant / to / put / B / in中的子目录。

在这些命令进入目录subdir / Iwant / to / put / B / in后,我看到B中的所有文件,但是其中任何一个上的 git log 都只显示提交消息合并B作为subdir / Iwant / to / put / B / in中的子目录。它们在B文件中的历史记录已丢失。



看起来工作起来了(因为我是git的初学者,可能我错了)是以下内容:

  git remote add -f B  
git checkout -b B_branch B / master#在B的master上创建一个本地分支
git filter-branch --index-filter \
'git ls-files -s | seds-\ 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 ,其中I只是改变了子目录路径。

解决方案

在得到关于发生了什么的更全面的解释之后,我想我明白了,在这种情况下,我有一个解决方法,具体来说,我相信正在发生的事情是重命名检测被与--prefix合并的子树所迷惑,这里是我的测试用例:

  mkdir -pz / az / 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
git commit -a -m BB
cd ../ a
git remote add -f B ../b
git merge -s我们的--no-commit B / master
git读取树--prefix = bdir -u B / master
git commit -msubtree merge B into bdir
cd bdir
echo BBB>> B
git commit -a -m BBB

我们使用git目录a和b分别进行多次提交。我们做一个子树合并,然后在新的子树中执行
a final commit。



运行 gitk (在z / a中)表明历史确实出现,我们可以看到它。运行 git log 会显示历史确实出现。然而,看一个特定的文件有一个问题: git log bdir / B



那么,有一个技巧我们可以玩。我们可以使用--follow来查看特定文件的预重命名历史记录。 git log --follow - B 。这很好,但不是很好,因为它无法将预合并的历史链接与合并后的链接关联起来。



我尝试使用-M和-C ,但我无法得到它遵循一个特定的文件。



所以,我觉得解决方案是告诉git有关将要进行的重命名作为子树合并的一部分。不幸的是,git-read-tree对于子树合并非常挑剔,所以我们必须通过一个临时目录,但是在我们提交之前它可能会消失。首先,创建一个A仓库并进行一些提交:




pre> mkdir -pz / az / 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我们的--no-commit B / maste r
git read-tree --prefix = -u B / master
git commit -msubtree merge B into bdir

为了表明它们现在被合并:

  cd bdir 
echo BBB>> B
git commit -a -m BBB

证明完整的历史保存在一个连接的链中:

  git log --follow B 

我们在这样做后得到历史记录,但问题是,如果您实际上保留旧的b回购协议并偶尔从中合并它实际上是第三方单独维护的回购),因为第三方不会进行重命名,所以您有麻烦。您必须尝试将新的更改合并到您的b版本中,并担心这种情况不会顺利进行。但是如果b消失了,你就赢了。

I'd like to merge a remote git repository in my working git repository as a subdirectory of it. I'd like the resulting repository to contain the merged history of the two repositories and also that each file of the merged-in repository retain its history as it was in the remote repository. I tried using the subtree strategy as mentioned in How to use the subtree merge strategy, but after following that procedure, although the resulting repository contains indeed the merged history of the two repositories, individual files coming from the remote one haven't retained their history (`git log' on any of them just shows a message "Merged branch...").

Also I don't want to use submodules because I do not want the two combined git repositories to be separate anymore.

Is it possible to merge a remote git repository in another one as a subdirectory with individual files coming from the remote repository retaining their history?

Thanks very much for any help.

EDIT: I'm currently trying out a solution that uses git filter-branch to rewrite the merged-in repository history. It does seem to work, but I need to test it some more. I'll return to report on my findings.

EDIT 2: In hope I make myself more clear I give the exact commands I used with git's subtree strategy, which result in apparent loss of history of the files of the remote repository. Let A be the git repo I'm currently working in and B the git repo I'd like to incorporate into A as a subdirectory of it. It did the following:

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

After these commands and going into directory subdir/Iwant/to/put/B/in, I see all files of B, but git log on any one of them shows just the commit message "Merge B as subdirectory in subdir/Iwant/to/put/B/in." Their file history as it is in B is lost.

What seems to work (since I'm a beginner on git I may be wrong) is the following:

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

The command above for filter-branch is taken from git help filter-branch, in which I only changed the subdir path.

解决方案

After getting the fuller explanation of what is going on, I think I understand it and in any case at the bottom I have a workaround. Specifically, I believe what is happening is rename detection is being fooled by the subtree merge with --prefix. Here is my test case:

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

We make git directories a and b with several commits each. We do a subtree merge, and then we do a final commit in the new subtree.

Running gitk (in z/a) shows that the history does appear, we can see it. Running git log shows that the history does appear. However, looking at a specific file has a problem: git log bdir/B

Well, there is a trick we can play. We can look at the pre-rename history of a specific file using --follow. git log --follow -- B. This is good but isn't great since it fails to link the history of the pre-merge with the post-merge.

I tried playing with -M and -C, but I wasn't able to get it to follow one specific file.

So, the solution, I feel, is to tell git about the rename that will be taking place as part of the subtree merge. Unfortunately git-read-tree is pretty fussy about subtree merges so we have to work through a temporary directory, but that can go away before we commit. Afterwards, we can see the full history.

First, create an "A" repository and make some commits:

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

Second, create a "B" repository and make some commits:

cd ../b
git init
echo B>B
git add B
git commit -m B
echo BB>>B
git commit -a -m BB

And the trick to making this work: force Git to recognize the rename by creating a subdirectory and moving the contents into it.

mkdir bdir
git mv B bdir
git commit -a -m bdir-rename

Return to repository "A" and fetch and merge the contents of "B":

cd ../a
git remote add -f B ../b
git merge -s ours --no-commit B/master
git read-tree --prefix= -u B/master
git commit -m "subtree merge B into bdir"

To show that they're now merged:

cd bdir
echo BBB>>B
git commit -a -m BBB

To prove the full history is preserved in a connected chain:

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存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆