8

プロジェクトに組み込む前に、git のサブツリーが機能することを確認しようとしています。サブツリーの変更をアップストリーム リポジトリにプッシュするときに問題が発生しました。

セットアップは、2 つのリポジトリと がsubありmain、これにはリポジトリが としてmain含まれています。subsubtree

次に、次のことを行います。

  1. 最初のコミットで両方のリポジトリを初期化します。
  2. subリポジトリを直接更新します (つまり、外部main)。
  3. subリポジトリ内からリポジトリを更新しますmain
  4. sub(を使用して) への変更をgit subtree split別のブランチに分割し、それをチェックアウトします。
  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のコマンド ( のsplit-branchブランチからmain) は、「既に最新です」と言うだけです。

私が本当に混乱しているのは、私が知る限り、次の出力git pushで示されているように、コマンドは実際にはアップストリーム リポジトリに早送りコミットを与える必要があるということです。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

これが私の質問です(最後に):

  1. このプッシュが拒否されるのはなぜですか?
  2. 私はそれについて何ができますか?(--forceオプションを使用することが答えである場合、破壊的なことをしていないことをどのように確認できますか?)
  3. subtreeこの問題を回避するためにモジュールを使用するより良い方法はありますか? (注: サブモジュールを使用する気はありません。)
4

1 に答える 1

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 master期待どおりに、現在チェックアウトされているブランチにのヘッドをフェッチしてマージsub-remote/masterします。ただしgit push sub-remote master、チェックアウトしたブランチのヘッドを にプッシュしませんsub-remote/master。同じ名前のブランチをプッシュします。したがって、この場合はmaster、上記の出力でわかるように です。

からgit help push(構文はgit push <repsitory> <refspec>):

パラメーターの形式<refspec>は、オプションのプラス + の後にソース ref<src>が続き、その後にコロン:が続き、その後に宛先 ref が続きます<dst>。リモートリポジトリ<src>の参照を更新するオブジェクトを指定するために使用されます。<dst>

<dst>は、リモート側のどの参照がこのプッシュで更新されるかを示します。ここでは任意の式を使用できません。実際の参照名を指定する必要があります。が省略された場合:<dst>、同じ参照<src>が更新されます。

したがって、探しているコマンドはgit push sub-remote splitbranch:master. でも、git subtree pushそもそもなんで使わないの?

于 2013-04-24T08:27:26.263 に答える