18

私は元々、いくつかの依存コードにサブモジュールを使用していたプロジェクトを持っています。サブモジュールはこのプロジェクトにはあまり適していない (実際には使いにくい) ことが判明したため、各サブモジュールをサブツリーに変換しています (新git-subtree機能を使用)。

私の作業リポジトリでは、各サブモジュールを正常に削除し、古いサブモジュール リポジトリをサブツリーとして追加しました。これで問題ありません。

別のクローンに移動して最初のクローンからプルしようとすると、マージ ステップで次のエラーが発生します。

error: The following untracked working tree files would be overwritten by merge:
        sub/.gitignore
        sub/Makefile
        sub/README
        sub/src/main.c
        ... and so on for all files in sub/
Aborting

これは、ファイルがsub/そもそもメイン リポジトリに実際に存在したことがなく、Git がパッチを適用して更新するとき.gitmodulesに、サブモジュール ファイルを含むディレクトリが削除されないことが原因のようです。次のコミットを処理するときに、Gitsub/現在メイン リポジトリの一部である に新しいファイルを作成しようとすると、それらのファイルはすべて にまだ存在するファイルと競合します。sub/

私が見つけた回避策は、この問題を回避するrm -rf subbeforeを使用することです。git pull

私の質問は、git merge「作業ディレクトリにたまたま存在するファイルを上書きする」というコマンドラインスイッチはありますか? さらに良いのはgit merge、既存のファイルの内容を確認する機能であり、作成しようとしていたファイルと内容が同じ場合は、エラー メッセージを抑制して続行します。

更新:私が話していることを正確に示すために、この問題を示すGitリポジトリを作成しました。再現するには:

$ git clone https://github.com/ghewgill/q14224966.git
$ cd q14224966
$ git submodule init
$ git submodule update
$ git merge origin/branch

これにより、エラーメッセージが表示されるはずです

error: The following untracked working tree files would be overwritten by merge:
    sub/Makefile
    sub/README
    sub/src/main.c
Please move or remove them before you can merge.
Aborting
4

4 に答える 4

11

あなたの質問がマージに固有のものであることは知っていますが、git サブモジュールのマージで同様の問題が発生しました。マージの質問に直接対処していなくても、この解決策はあなたの問題でうまくいくと思います。

マージしたいブランチを強制的にチェックアウトしてからマスターに戻ると、サブモジュールですべてがうまくいくことがわかりました。

あなたの例で物事を機能させるには:

$ git clone https://github.com/ghewgill/q14224966.git
$ cd q14224966
$ git submodule init
$ git submodule update
$ git checkout -f origin/branch
$ git checkout master
$ git merge origin/branch

これは、基本的にあなたのrm -rfステップを実行しているため機能します。確かに、これは少し回り道であり、例のようにサブモジュールが 1 つしかない場合は、実行する価値がないかもしれません。しかし、多くのサブモジュールを含むプロジェクトで作業する場合、これは非常に時間の節約になることがわかりました。

また、コメントで指摘されているように、作業ツリーに変更を加えたくない場合は、これを使用できます。

$ git clone https://github.com/ghewgill/q14224966.git
$ cd q14224966
$ git submodule init
$ git submodule update
$ git reset origin/branch
$ git reset --hard master

これはほぼ同じように機能しますが、プロセス内の他のファイルのチェックアウトを回避します。これを実際に使用する機会はありませんでしたが、健全な方法のようです。

もあり$ git merge -s subtree origin/branchます。あなたの例では動作しますが、複数のサブモジュールが関係している場合、予期しない結果が発生しました。ただし、運が良いかもしれません。

于 2013-01-21T23:03:41.070 に答える
1

git-merge認識していないと思われるファイルを強制的にクロバーすることはできません(または他のコマンドを使用することはできません)。git は、完全に元に戻せないことをしないようにかなりの努力を払っています。

ただし、多くのサブモジュールを使用すると、次の方法で削除を少し簡単かつ安全にすることができgit submodule foreachます。

$ git submodule foreach 'rm -rf $toplevel/$path'
Entering 'sub'
$ git merge origin/branch
Updating a231acd..6b4d2f4
Fast-forward
...
于 2013-01-25T23:32:21.603 に答える
1

(注意: 私はサブツリーを扱ったことがなく、実際のレポがどれほど複雑なのかわかりません。そのため、これらのソリューションは実際には機能しない可能性があります。)

サンプル リポジトリをいじってみると、異なるコミット ツリーが生成されますが、両方とも機能するように見える 2 つのソリューションが見つかりました。

  1. 使用するgit merge -s resolve origin/branch

    ~/q14224966[master]> git reset --hard origin/master
    HEAD is now at a231acd add submodule
    ~/q14224966[master]> touch other.c && git add . && git commit -m "New commit."
    [master bc771ac] New commit.
     0 files changed
     create mode 100644 other.c
    ~/q14224966[master]> git merge -s resolve origin/branch 
    Trying really trivial in-index merge...
    error: Merge requires file-level merging
    Nope.
    Trying simple merge.
    Simple merge failed, trying Automatic merge.
    Adding sub/Makefile
    Adding sub/README
    Adding sub/src/main.c
    Merge made by the 'resolve' strategy.
     .gitmodules    | 3 ---
     sub            | 1 -
     sub/Makefile   | 1 +
     sub/README     | 1 +
     sub/src/main.c | 1 +
     5 files changed, 3 insertions(+), 4 deletions(-)
     delete mode 160000 sub
     create mode 100644 sub/Makefile
     create mode 100644 sub/README
     create mode 100644 sub/src/main.c
    ~/q14224966[master]> ls
    README   main.c   other.c  sub/
    ~/q14224966[master]> cd sub/
    ~/q14224966/sub[master]> ls
    Makefile  README    src/
    ~/q14224966/sub[master]> git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 5 commits.
    #
    nothing to commit (working directory clean)
    ~/q14224966/sub[master]> cd ..
    ~/q14224966[master]> git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 5 commits.
    #
    nothing to commit (working directory clean)
    

    結果のコミット ツリーは次のとおりです。git コミット ツリー - マージ オプション

  2. マージの代わりにリベースを使用します。

    ~/q14224966[master]> git reset --hard origin/master 
    HEAD is now at a231acd add submodule
    ~/q14224966[master]> touch other.c && git add . && git commit -m "New commit."
    [master ae66060] New commit.
     0 files changed
     create mode 100644 other.c
    ~/q14224966[master]> git rebase origin/branch 
    First, rewinding head to replay your work on top of it...
    Applying: New commit.
    ~/q14224966[master]> ls
    README   main.c   other.c  sub/
    ~/q14224966[master]> cd sub/
    ~/q14224966/sub[master]> ls
    Makefile  README    src/
    ~/q14224966/sub[master]> git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 4 commits.
    #
    nothing to commit (working directory clean)
    ~/q14224966/sub[master]> cd ..
    ~/q14224966[master]> git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 4 commits.
    #
    nothing to commit (working directory clean)
    

    結果のコミット ツリーは次のとおりです。git コミット ツリー - リベース オプション

于 2013-01-26T18:56:12.703 に答える
0

試した

git フェッチ --all

git reset --hard オリジン/マスター

しかし、うまくいきません。

「ours」マージ戦略を使用できます。

git merge -s 私たちの古いマスター

git-stash を使用して変更を保存し、git-stash apply を使用してそれらを復元することもできます。

于 2013-01-26T09:38:29.133 に答える