简体   繁体   English

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

[英]Pushing git subtree changes to upstream repository fails

I'm trying to ensure that git's subtrees will work for me before I incorporate it into my project. 我试图确保git的子树在我合并到我的项目之前对我有用。 I encountered a problem when pushing subtree changes to the upstream repository. 将子树更改推送到上游存储库时遇到问题。

The setup is that I have two repos, sub and main , and that main includes the sub repo as a subtree . 设置是我有两个repos, submain ,并且main包括sub repo作为subtree

Then I do the following: 然后我做以下事情:

  1. Initialize both repos with an initial commit. 使用初始提交初始化两个repos。
  2. Update the sub repo directly (ie outside of main ). 直接更新sub仓库(即在main仓外)。
  3. Update the sub repo from within the main repo. 更新main仓库中的sub仓库。
  4. Split the changes to sub (using git subtree split ) into a separate branch, which I then checkout. 将更改拆分为sub (使用git subtree split )到一个单独的分支,然后我将其签出。
  5. Attempt to push upstream to the sub repo. 尝试将上游推送到sub仓库。 Naturally, this push is rejected because it would lose the direct update to sub . 当然,这种推动被拒绝,因为它将失去对sub的直接更新。
  6. Pull the new change from the sub repo. sub仓库中拉出新的更改。
  7. Attempt to push upstream to the sub repo. 尝试将上游推送到sub仓库。 This time, it should work, but it doesn't. 这一次,它应该工作,但事实并非如此。

I've written a script that encapsulates this problem. 我写了一个封装这个问题的脚本。 I'm using git version 1.8.2.1 with the subtree module enabled. 我正在使用git版本1.8.2.1并启用了subtree模块。 Here's the script: 这是脚本:

#!/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 ..

And here's the output: 这是输出:

$ ./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.

Further git pull commands (from the split-branch branch of main ) simply say "Already up-to-date". 进一步的git pull命令(来自mainsplit-branch分支)简单地说“已经是最新的”。

The thing that's really confusing to me is that, as far as I can tell, the git push command should really be giving the upstream repo a fast-forward commit, as demonstrated by the following git log output: 对我来说真正令人困惑的是,据我所知, git push命令应该真正为上游repo提供快进提交,如下面的git log输出所示:

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

Here are my questions (finally): 以下是我的问题(最后):

  1. Why is this push rejected? 为什么这个推被拒绝了?
  2. What can I do about it? 我能做些什么呢? (If using the --force option is the answer, how can I be certain I am not doing something destructive?) (如果使用--force选项是答案,我怎么能确定我没有做破坏性的事情?)
  3. Is there a better way to use the subtree module to avoid this problem? 有没有更好的方法来使用subtree模块来避免这个问题? (Note: I'm not willing to use submodules.) (注意:我不愿意使用子模块。)

Your problem is not really related to git subtree . 你的问题与git subtree无关。 You having problems with the good old tricky git ui. 你有好老的棘手的git ui的问题。 In this case git push . 在这种情况下git push You obviously assumed that its syntax follows git pull . 你显然假设它的语法遵循git pull That was rather naive – you are using git ;). 这很天真 - 你正在使用git;)。

You push output tells you what is wrong here: 你推输出告诉你这里有什么问题:

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

git pull sub-remote master fetches and merges the head of sub-remote/master into your currently checked-out branch, just as you expected. git pull sub-remote master取出并将sub-remote/master的头部合并到当前签出的分支中,就像你期望的那样。 But git push sub-remote master does not push the head of your checked-out branch into sub-remote/master . 但是git push sub-remote master不会将签出分支的头部推入sub-remote/master It does push the branch of the same name. 它确实推动了同名的分支。 So in this case that is master , as you can see in the output above. 所以在这种情况下是master ,正如你在上面的输出中看到的那样。

From git help push (syntax is git push <repsitory> <refspec> ): git help push (语法是git push <repsitory> <refspec> ):

The format of a <refspec> parameter is an optional plus +, followed by the source ref <src> , followed by a colon : , followed by the destination ref <dst> . <refspec>参数的格式是可选的+,后跟源ref <src> ,后跟冒号: ,后跟目标ref <dst> It is used to specify with what <src> object the <dst> ref in the remote repository is to be updated. 它用于指定要更新远程存储库中<dst> ref的<src>对象。

The <dst> tells which ref on the remote side is updated with this push. <dst>告诉使用此推送更新远程端的哪个ref。 Arbitrary expressions cannot be used here, an actual ref must be named. 这里不能使用任意表达式,必须命名实际的ref。 If :<dst> is omitted, the same ref as <src> will be updated. 如果:<dst>省略:<dst> ,将更新与<src>相同的引用。

So the command you are looking for is git push sub-remote splitbranch:master . 所以你要找的命令是git push sub-remote splitbranch:master But why are you not using git subtree push in the first place? 但是你为什么不首先使用git subtree push

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM