使用子树合并策略,历史不合并

时间:2012-05-17 11:20:27

标签: git subtree

我正在尝试通过“子树合并”将外部SVN存储库用作我的存储库中的子树。我相信这应该保持库中文件的历史记录不变,但它不起作用 - 从库中合并到我的主分支中的子树的文件没有历史记录,但是当我添加它们时提交 - 这是一个显示我的意思的历史记录,正是我将要进入这个状态的跟随。

lappy8086:YACYAML jamie$ git log --graph 
* commit 0cc6c4e5061741e67d009f3375ce1d2bcd3ab540
| Author: James Montgomerie
| Date:   Thu May 17 12:04:43 2012 +0100
| 
|     Subtree-merge in libYAML (from a git-svn checkout).
|  
* commit b5af5af109d77f6adafebc3dcf5a4796a5035a2e
Author: James Montgomerie
Date:   Thu May 17 11:47:32 2012 +0100

First commit, add .gitignore.

这就是我正在努力让它发挥作用:

# check out SVN repo
git svn clone http://svn.pyyaml.org/libyaml/branches/stable libYAML

# create my repo
mkdir YACYAML
cd YACYAML
git init
touch .gitignore
git add .gitignore
git commit -m "First commit, add .gitignore"

# Fetch from git-svn repo I got earlier
git remote add libyaml-svn ../libYAML/
git fetch libyaml-svn
git checkout -b libyaml-svn libyaml-svn/master

# Switch back to master, and try to merge in subtree
git checkout master
git read-tree --prefix=libYAML/ -u libyaml-svn/master
git commit -m "Merge in libYAML as subtree (from git-svn checkout of SVN repo)"

这个“有效”,但是,正如我所说,当我查看我的历史时,我希望看到来自libYAML回购的完整历史记录,但我没有 - 就像上面一样。

2 个答案:

答案 0 :(得分:2)

嗯,一个答案是安装git-subtree并将其用于:

git subtree add --prefix=libYAML/ ../libYAML master

这会导致我手动执行此操作(以及预期):

lappy8086:YACYAML jamie$ git log --graph
*   commit 453d464cfc140c798d0dea85ab667fe16250181d
|\  Merge: 9fb083d 0ca365a
| | Author: James Montgomerie 
| | Date:   Thu May 17 14:32:36 2012 +0100
| | 
| |     Add 'libYAML/' from commit '0ca365adeb5711bf918d4401e98fce00bab8b3ec'
| |     
| |     git-subtree-dir: libYAML
| |     git-subtree-mainline: 9fb083d923011dd990222da2a58eda42e5220cde
| |     git-subtree-split: 0ca365adeb5711bf918d4401e98fce00bab8b3ec
| |   
| * commit 0ca365adeb5711bf918d4401e98fce00bab8b3ec
| | Author: xi
| | Date:   Sun May 29 05:52:36 2011 +0000
| | 
| |     Bumped the version number and updated the announcement.
| |     
| |     git-svn-id: http://svn.pyyaml.org/libyaml/branches/stable@374 18f92427-320e-0410-9341-c67f048884a3
| |   
| * commit 210b313e5ab158f32d8f09db6a8df8cb9bd6a982
| | Author: xi
| | Date:   Sun May 29 05:29:39 2011 +0000
| | 
| |     Added support for pkg-config.
| |     
| |     git-svn-id: http://svn.pyyaml.org/libyaml/branches/stable@373 18f92427-320e-0410-9341-c67f048884a3
...etc...

我仍然想知道正确的方法,而不依赖于git-subtree。

答案 1 :(得分:2)

当合并包括在子目录中重新显示树时,git log [--follow] <filename>的行为似乎不一致,如git subtree那样。

我进行了一些实验,如果您在第一个子树合并之前在源代码行上引入合成重新提交提交,则会通过git log --follow <filename>开始报告历史记录。

我可以看到的选项:

  1. 修复git log以关注在合并期间发生的重命名
  2. 更改git subtree为每次添加创建两个提交,首先在一次提交中重新创建树,然后在之后合并重新提交的提交
  3. 通过.git/info/graftsgit filter-branch
  4. 完成#2,手动解决问题

    解决方法:

    $ git log --grep git-subtree-mainline
    commit 8789f3c80122d1fc52ff43ab776a7b186f51c3c6
    Merge: 0c11300 4757376
    Author: John Sumsion <email>
    Date:   Wed Apr 17 09:43:21 2013
    
        Add 'some-subdir/' from commit 'f54875a391499f910eeb8d6ff3e6b00f9778a8ab'
    
        git-subtree-dir: some-subdir
        git-subtree-mainline: 0c113003278e58d32116c8bd5a60f2c848b61bbb
        git-subtree-split: f54875a391499f910eeb8d6ff3e6b00f9778a8ab
    $ git checkout -b fix 
    Switched to a new branch 'fix'
    $ mkdir -p some-subdir
    $ git mv <files> some-subdir
    $ git commit -m "Re-parenting files before subtree merge to preserve 'git log --follow' history"
    $ echo <orig_merge> <orig_parent> <fixed_merge_parent> >> .git/info/grafts
    $ git filter-branch --index-filter true --tag-name-filter cat master
    

    以下提交的地方是:

    • orig_merge:8789f3c80122d1fc52ff43ab776a7b186f51c3c6
    • orig_parent:0c113003278e58d32116c8bd5a60f2c848b61bbb
    • fixed_merge_parent:来自git commit
    • 的sha

    不幸的是,在第一个子树合并之后通过git subtree合并的后续更改似乎没有通过git log --follow <filename>报告,即使第一个子树合并是合成重新替换的。

    出于某种原因,我似乎记得这在Git 1.7.x时间框架中运行正常,但这是一个遥远过去的模糊记忆,我没有时间研究。用Git 1.8.3.2观察到上述情况。