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

标签 git push git-push git-subtree

在将 git 的子树 merge 到我的项目中之前,我试图确保它对我有用。我在将子树更改推送到上游存储库时遇到问题。

设置是我有两个 repos,submainmain 包含 sub作为 子树 的 repo。

然后我执行以下操作:

  1. 使用初始提交初始化两个存储库。
  2. 直接更新 sub 存储库(即在 main 之外)。
  3. main 存储库中更新 sub 存储库。
  4. 将对 sub 的更改(使用 git subtree split)拆分到一个单独的分支中,然后我将其 check out 。
  5. 尝试向上游推送到 sub 存储库。自然地,这个推送被拒绝了,因为它会丢失对 sub 的直接更新。
  6. sub 存储库中提取新更改。
  7. 尝试向上游推送到 sub 存储库。这一次,它应该会起作用,但它并没有起作用。

我写了一个脚本来封装这个问题。我正在使用启用了 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 命令(来自 mainsplit-branch 分支)简单地说“已经是最新的”。

真正让我感到困惑的是,据我所知,git push 命令实际上应该为上游存储库提供快进提交,如下面的 git 日志 输出:

$ ( 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. 为什么这个推送被拒绝了?
  2. 我该怎么办? (如果使用 --force 选项是答案,我怎么能确定我没有做破坏性的事情?)
  3. 有没有更好的方法使用subtree模块来避免这个问题? (注意:我不愿意使用子模块。)

最佳答案

您的问题实际上与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 master获取并 merge sub-remote/master 的头部进入您当前 checkout 的分支,正如您所期望的那样。但是git push sub-remote master不会将 checkout 分支的负责人 push sub-remote/master .它确实推送同名分支。所以在这种情况下是 master ,如您在上面的输出中所见。

来自 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>. It is used to specify with what <src> object the <dst> ref in the remote repository is to be updated.

The <dst> tells which ref on the remote side is updated with this push. Arbitrary expressions cannot be used here, an actual ref must be named. If :<dst> is omitted, the same ref as <src> will be updated.

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

关于git - 将 git 子树更改推送到上游存储库失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16112836/

相关文章:

git - `git push` 是否用作 `git push origin newfeature` 的简写?

git - Visual Studio Code 是否有类似 IntelliJ 的功能 "Compare with branch"

linux - 致命: destination path '/var/cpanel/easy/apache/custom_opt_mods/Cpanel already exists and is not an empty directory

android - 使用 Firebase 的一对一 Android 聊天

git push --set-upstream vs --set-upstream-to

git - 致命的 : unable to create 'refs/heads/master.lock' : File exists fatal: - Getting this error while pushing the commits

git - 我可以推送在分离的 HEAD 状态下进行的提交吗

git - 克隆 pull 请求

wordpress - 带有部分工作树的 Git 后接收 Hook

javascript - 如何在屏幕上实时向与第一个用户一起玩的其他用户显示用户的游戏分数?