将git子树更改推送到上游存储库失败

时间:2013-04-19 20:16:51

标签: git push git-push git-subtree

我尝试确保git的子树在我合并到我的项目之前对我有用。将子树更改推送到上游存储库时遇到了问题。

设置是我有两个回购,submain,并且mainsub回购包含为subtree

然后我执行以下操作:

  1. 使用初始提交初始化两个repos。
  2. 直接更新sub回购(即main之外)。
  3. 更新sub回购中的main回购。
  4. 将更改拆分为sub(使用git subtree split)到一个单独的分支,然后我将结帐。
  5. 尝试将上游推送到sub回购。当然,这种推送被拒绝,因为它会失去对sub的直接更新。
  6. sub repo。
  7. 中提取新的更改
  8. 尝试将上游推送到sub回购。这一次,它应该有效,但它没有。
  9. 我编写了一个封装此问题的脚本。我在启用subtree模块的情况下使用git版本1.8.2.1。这是脚本:

    #!/bin/bash
    
    echo -n "Wiping old repositories..."
    rm -rf main sub sub-home
    echo "done"
    
    echo -n "Initializing main and sub repositories..."
    mkdir sub-home
    ( cd sub-home ; git init -q --bare )
    git clone sub-home sub > /dev/null 2>&1
    ( cd sub ; echo subfile > subfile ; git add subfile ;
      git commit -qm "adding root-level file to sub-project" ;
      git push -q origin master )
    mkdir main
    ( cd main ; git init -q ; echo file > file ; git add file ;
      git commit -qm "adding root-level file to main-project" )
    echo "done"
    
    echo -n "Adding sub project as a subtree into main project..."
    WD=$PWD
    ( cd main ; git remote add sub-remote file://$WD/sub-home ;
      git subtree add -P sub sub-remote master >/dev/null 2>&1 )
    echo "done"
    
    echo -n "Committing to sub-project directly..."
    ( cd sub ; date > the-date ; git add the-date ;
      git commit -qm "adding the-date to sub-project"
      git push -q origin master )
    echo "done"
    
    echo -n "Committing to sub-project from within main project..."
    ( cd main ; echo 'subfile what?' > sub/subfile ; git add sub/subfile ;
      git commit -qm "changing sub-project from within the main project" )
    echo "done"
    
    cd main
    git subtree split -q -P sub -b split-branch >/dev/null
    git checkout -q split-branch
    echo -e "\nPushing from main subtree to sub project, which should fail:"
    git push sub-remote master
    echo -e "\nBut if we pull first..."
    git pull -q --no-edit sub-remote master
    echo "...then a push *should* work (but it doesn't):"
    git push sub-remote master
    cd ..
    

    这是输出:

    $ ./test.sh
    Wiping old repositories...done
    Initializing main and sub repositories...done
    Adding sub project as a subtree into main project...done
    Committing to sub-project directly...done
    Committing to sub-project from within main project...done
    
    Pushing from main subtree to sub project, which should fail:
    To file:///tmp/git/sub-home
     ! [rejected]        master -> master (fetch first)
    error: failed to push some refs to 'file:///tmp/git/sub-home'
    hint: Updates were rejected because the remote contains work that you do
    hint: not have locally. This is usually caused by another repository pushing
    hint: to the same ref. You may want to first merge the remote changes (e.g.,
    hint: 'git pull') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
    
    But if we pull first...
    ...then a push *should* work (but it doesn't):
    To file:///tmp/git/sub-home
     ! [rejected]        master -> master (non-fast-forward)
    error: failed to push some refs to 'file:///tmp/git/sub-home'
    hint: Updates were rejected because a pushed branch tip is behind its remote
    hint: counterpart. Check out this branch and merge the remote changes
    hint: (e.g. 'git pull') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
    

    其他git pull命令(来自split-branch的{​​{1}}分支)只是说"已经是最新的"。

    对我来说真正令人困惑的是,就我所知,main命令应该真正给上游回购提供快速提交,如下所示{ {1}}输出:

    git push

    以下是我的问题(最后):

    1. 为什么拒绝这个推?
    2. 我该怎么办? (如果使用git log选项是答案,我怎么能确定我没有做破坏性的事情?)
    3. 有没有更好的方法来使用$ ( cd main ; git log ) commit 357fe9fb42f5d122338940eb4f22d3ca9d276318 Merge: 472904f cb5d1d3 Author: Jeff Terrell <jeff.terrell@acm.org> Date: Fri Apr 19 16:03:03 2013 -0400 Merge branch 'master' of file:///tmp/git/sub-home into split-branch commit 472904f432c3a0a89acde02691b8281ac5246fd1 Author: Jeff Terrell <jeff.terrell@acm.org> Date: Fri Apr 19 16:03:02 2013 -0400 changing sub-project from within the main project commit cb5d1d34ce56374f78c98c5b3f3daa314907b62d Author: Jeff Terrell <jeff.terrell@acm.org> Date: Fri Apr 19 16:03:02 2013 -0400 adding the-date to sub-project commit 7d1942203d30e0d9e8663517e6d594545bc50640 Author: Jeff Terrell <jeff.terrell@acm.org> Date: Fri Apr 19 16:03:02 2013 -0400 adding root-level file to sub-project $ (cd sub ; git log ) commit cb5d1d34ce56374f78c98c5b3f3daa314907b62d Author: Jeff Terrell <jeff.terrell@acm.org> Date: Fri Apr 19 16:03:02 2013 -0400 adding the-date to sub-project commit 7d1942203d30e0d9e8663517e6d594545bc50640 Author: Jeff Terrell <jeff.terrell@acm.org> Date: Fri Apr 19 16:03:02 2013 -0400 adding root-level file to sub-project 模块来避免这个问题? (注意:我不愿意使用子模块。)

1 个答案:

答案 0 :(得分:8)

您的问题与git subtree无关。你有好老的棘手的git ui的问题。在这种情况下git push。您显然假设其语法遵循git pull。这很天真 - 你正在使用git;)。

你推输出告诉你这里有什么问题:

To file:///tmp/git/sub-home
! [rejected]        master -> master (non-fast-forward)

git pull sub-remote mastersub-remote/master的头部提取并合并到您当前签出的分支中,就像您预期的那样。但git push sub-remote master并未将签出分支的头部推入sub-remote/master。它确实推动了同名的分支。所以在这种情况下是master,正如您在上面的输出中所看到的那样。

来自git help push(语法为git push <repsitory> <refspec>):

  

<refspec>参数的格式是可选加+,后跟源引用<src>,后跟冒号:,后跟目标引用<dst> 。它用于指定要更新远程存储库中<src> ref的<dst>对象。

     

<dst>通过此推送告知远程端的哪个ref更新。这里不能使用任意表达式,必须命名实际的ref。如果省略:<dst>,则会更新与<src>相同的参考号。

所以你要找的命令是git push sub-remote splitbranch:master。但是你为什么不首先使用git subtree push