git-subtree添加后如何rebase?
我试图学习Git 1.7.11中添加的新的git-subtree命令。 我添加一个子树后,似乎失去了rebase的能力。 我有与自述文件和库存储库,也有自述文件的主要存储库。 我将它添加到subtree add
lib目录:
$ git subtree add -P lib/mylib myliborigin master
这工作正常,但现在的历史看起来像这样:
* 22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' - |\ | * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3d * b99d55b Add readme * 020e372 Initial
现在,当我想重新对我的repo对origin/master
,它失败,因为南瓜提交是直接应用于其父提交不适用,因为它是应用于回购的根,而不是我给它的前缀添加子树时。
这样做的原因很明显,如果我看看南瓜的承诺。 没有关于前缀的信息。 这只是原来的mylib承诺压在一起。 只有下一个合并提交知道它的任何事情,但是rebase并没有把它记在这里。
是否有任何解决方法(除了从不分配subtree提交)?
这不是一个解决scheme,但它目前的工作,我使用…
用你最初的例子:
* 22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' - |\ | * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3d * b99d55b Add readme * 020e372 Initial
交互地重新添加到子树添加之前的第二次提交:
$ git rebase -i 020e372
删除两个子树条目并为之前的提交标记编辑:
e b99d55b Add readme
保存文件/closures,然后当它进入“添加自述文件”提交,运行修改命令:
$ git commit --amend
然后重新添加你的新子树:
$ git subtree add -P lib/mylib myliborigin master
继续rebase:
$ git rebase --continue
然后,你的分支应该被重新设置为主,并且该子树将与“壁球+合并”完好无损:
* 22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' - |\ | * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3d
这是一个古老的问题,但我只是有我的回购相同的问题,我终于find了一个完整的解决scheme,(希望)保留所有的子树元数据。
假设我们有这个提交树:
B (master) Add README.md | A Initial commit
我们用一个驻留在lib/
的子树分支了一个feature
分支:
git remote add -f githublib https://github.com/lib/lib.git git subtree add --prefix lib/ githublib master --squash
它创build一个合并提交D与两个父母:我们当前的master
(B)和一个不相关的提交F
与外部回购的压扁的历史。 这个提交在其提交消息中还包含一些git subtree
元数据(即, git-subtree-dir
和git-subtree-split
)。
D (feature) Merged commit 'F' as 'lib/' / \ / F Squashed 'lib/' content from GGGGGG B (master) Add README.md | A Initial commit
之后,我们向两个分支独立地添加一些提交。
E (feature) Remove .gitignore from lib/ C | (master) Add LICENSE.md | D Merged commit 'F' as 'lib/' | / \ |/ F Squashed 'lib/' content from GGGGGG B Add README.md | A Initial commit
现在我们想要将feature
重新映射到master
。 就是这样:
1.樱桃 – 从feature
一个接一个提交创buildfeature
分支的master
副本的新副本。
git branch -f feature C git checkout feature git cherry-pick DE E' (feature) Remove .gitignore from lib/ | D' Merged commit 'F' as 'lib/' | | E Remove .gitignore from lib/ C | (master) Add LICENSE.md | D Merged commit 'F' as 'lib/' | / \ |/ F Squashed 'lib/' content from GGGGGG B Add README.md | A Initial commit
现在我们有相当于一个rebase,但是我们已经失去了有关git subtree
所需的外部回购的所有信息。 要恢复它:
2. 添加缺less的父链接作为嫁接 ,并重写feature
的历史,使其永久。
git checkout feature git replace --graft D' CF git filter-branch --tag-name-filter cat -- master..
现在我们得到一张和刚开始的照片完全相同的照片。 旧的承诺D和E仍然在那里,但可以稍后垃圾收集。
E' (feature) Remove .gitignore from lib/ | D' Merged commit 'F' as 'lib/' |\ | \ C \ (master) Add LICENSE.md | \ | \ | F Squashed 'lib/' content from GGGGGG B Add README.md | A Initial commit
警告:这会重写feature
的历史logging,所以如果其他人在此分支上与您协作,请谨慎发布。 但是,既然你想首先做一个rebase,你可能会意识到:-)
显然这是预期的行为(对于“预期行为”的一些不正当的定义。)参见http://git.661346.n2.nabble.com/subtree-merges-lose-prefix-after-rebase-td7332850.html 。
这并不是说这对任何人都很有帮助。 我也很想find解决方法。
我有一个类似的问题:我想在做一个子树添加后重新绑定,并使用–preserve-merges仍然留给我一个合并冲突(由于冲突的.gitignore
文件和其他人)。
就我而言,我并不一定打算使用任何子树function:我只是简单地引入一个本来应该是超级项目一部分的回购。 如果它帮助其他人,根据我发现的其他相关 答案 ,这是我最终做的。
假设我有两个项目,main_project和sub_project,在同一个目录中。 我想将sub_project拖到main_project中的一个名为sub_project的目录中,假设没有repo曾经有一个名为sub_project的目录:
cd main_project git fetch ../sub_project git checkout -b sub_project FETCH_HEAD git filter-branch --prune-empty --tree-filter ' if [[ ! -e sub_project ]]; then mkdir -p sub_project git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files sub_project fi' git checkout branch-to-merge-within git merge sub_project git branch -d sub_project
如果我发现这种方法有任何问题,我会更新。
你需要使用
git rebase --preserve-merges --preserve-committer --onto new_place start end