9

デフォルトのgit-merge-one-fileプログラムを変更して、作業ツリーに触れずにインデックス内のすべてを実行し、完全に変更しないようにすることは可能ですか?

アップデートと詳細

したがって、ワークツリーを使用しないと、ファイル レベルのマージ (ファイル全体ではなくファイル内の行に対してマージが実行される場合) は発生しないことがわかりました。(ファイル全体に作用するマージとは異なります。)したがって、ワークツリーを使用する必要があります。

別の詳細: 手動で解決せずにマージを自動的に実行できる場合にのみ、ソリューションが機能することに問題はありません。マージが自動でない場合は、エラー メッセージが表示されるだけで問題ありません。(そしてもちろん、すべてをきれいにしておきます。)

別の詳細: 私はgit-merge-one-file直接使用していません。このスクリプト内で使用しています: https://gist.github.com/cool-RR/6575042

@torek のアドバイスに従い、(スクリプトでわかるように) 一時的な作業ツリーを使用しようとしました。問題は、次のエラーが発生することです。

git checkout-index: my_file is not in the cache
error: my_file: cannot add to the index - missing --add option?

これらのエラー メッセージをグーグル検索しましたが、役立つ情報が見つかりませんでした。

どうすればいいですか?

4

5 に答える 5

5

git には作業を行う場所が必要ですが、「1 つのファイルをマージする」操作の間、別の作業ツリーの場所を指し示すことができます。

これが「箱から出して」で機能するかどうか/どのように機能するかはわかりませんmerge-one-fileが、設定する環境変数は次のGIT_WORK_TREEとおりです。

env GIT_WORK_TREE=/some/where/else git ...

(envすべてではありませんが、ほとんどのシェルを省略できます)。

「より安全に感じる」かもしれない多かれ少なかれ同等の方法:-)またはいくつかの目的でより便利な方法は、他のディレクトリで作業しGIT_DIR、レポの場所に使用することです:

cd /some/where/else
env GIT_DIR=/place/with/repo/.git git ...

GIT_DIRと の両方を設定して、それらを組み合わせることもできますGIT_WORK_TREE

于 2013-09-13T16:18:34.287 に答える
2

いいえ、しかしそれを行う最も簡単な方法は、stash、merge、stage、および unstash です。

git stash save
git merge-file foo.txt base-foo.txt their-foo.txt
git add foo.txt
git stash pop

スタッシュしたくない場合は、差分とパッチのオプションが残されています。作業ツリーの変更をパッチに保存し、作業ツリーの変更を削除し、必要な変更を加えて、パッチを再適用します。

git diff -p --raw foo.txt > foo.txt.diff
git checkout -- foo.txt
git merge-file foo.txt base-foo.txt their-foo.txt
patch -p1 < foo.txt.diff    
于 2013-09-13T12:59:33.037 に答える
2

git でのマージは、以下の間の 3 方向のマージです。

  • ソース (' remote' または ' theirs', マージしたいもの)
  • 宛先 (' local' または ' ours'、常に HEAD がチェックアウトされている作業ツリー)
  • 共通の祖先 (または ' base')

「 」に示されている「 」local、「base」、「 」、remote「 」を参照し、「 」と「 」追跡します。「期待どおりに動作しない 」で例を確認できます。mergedgit rebaselocalremote
git revert

git read-tree「 Subtree Merging」および「Git Objects 」で言及されている(およびgistで使用していること)は、ファイルコンテンツ(blob)ではなく、ツリーのマージ(サブツリーのマージ用)に関するものです。
git write-treeツリーオブジェクトの作成に使用できますが、そのドキュメントには「インデックスは完全にマージされた状態でなければならない」と記載されています。(ファイルのマージにインデックスを使用する場合は少し難しい)。

git インデックス(ドキュメントはこちら)は、マージ解決の一部として、作業ツリーからステージングしたもの (' merged' 結果) を記録するためにあります。
ファイルの内容に関するすべての情報が含まれているわけではなく、その内容へのポインター(「インデックス エントリ」) のみが含まれています。マージを行うのは、単純に正しい構造ではありません。


スクリプト自体でさえgit-merge-one-file.sh言及しています:

require_work_tree

関数はgit-sh-setup.shスクリプトから取得されます (そのドキュメントを参照してください):

test "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = true ||
die "fatal: $0 cannot be used without a working tree."

その要件は、コミット 6aaeca90 ( peff Jeff King )から来ています。

1 つのファイルをマージするツールは、GIT_WORK_TREE.

ほとんどの場合、merge-one-fileで動作しGIT_WORK_TREEます; その重労働のほとんどは、GIT_WORK_TREE適切に尊重する配管コマンドによって行われます。


作業ツリーを本当に使用する必要がない場合は、 Merging notesに選択されたルートを試すことができます:
notes-merge.c独自の作業ツリーを作成してgit notesをマージします。

于 2013-09-16T07:33:14.467 に答える
2

2 つの異なるファイルの変更をマージするには、その内容を調べる必要があります。変更のマージは、ファイルの内容に取り組んでいます。コンテンツの作業は作業ツリーで行われます。作業を別の場所で行い、作業ツリーではないふりをするのは単なる言葉遊びです。

マージ中に現在のワークツリーを変更しない場合は、別のワークツリーを使用してください。git clone は安価で、次のような目的で構築されています。

# merge into branch m2 from branch m1 but leave your (non-m2) worktree untouched:
git clone --no-checkout -b m2 . ../m2-work
cd ../m2-work
git reset    # this will warn about the empty worktree, you could instead do
#              git read-tree HEAD to get the same effect without the chatter
git merge origin/m1
git push origin m2

--no-checkoutクローンの に注意してください。Merge は作業を行うためにワークツリーを持っている必要がありますが、比較が必要なもの以外の実際のファイルの内容は気にしません。

于 2013-09-15T18:20:42.683 に答える
1

Jeff Kingが問題の解決を手伝ってくれたので、スクリプトを更新して動作させました。

https://gist.github.com/cool-RR/6575042

#!bash
if [ -n "$2" ]; then
  export SOURCE=$1 ;
  export DESTINATION=$2 ;
else
  export SOURCE=HEAD ;
  export DESTINATION=$1 ;
fi

export GIT_INDEX_FILE=`git rev-parse --show-toplevel`/.git/aux-merge-index ;
export GIT_WORK_TREE=`create_temporary_folder gm_`;
echo $GIT_INDEX_FILE
trap 'rm -f '"'$GIT_INDEX_FILE'"'; rm -rf '"'$GIT_WORK_TREE'" 0 1 2 3 15 ;
mkdir $GIT_WORK_TREE/.git
set -e ;
git read-tree -im `git merge-base $DESTINATION $SOURCE` $DESTINATION $SOURCE ;
#echo Finished read-tree
#sleep 1000
git merge-index git-merge-one-file -a
#echo Finished merge-index
git write-tree \
| xargs -i@ git commit-tree @ -p $DESTINATION -p $SOURCE -m "Merge $SOURCE into $DESTINATION" \
| xargs git update-ref -m"Merge $SOURCE into $DESTINATION" refs/heads/$DESTINATION ;
exit 0
于 2013-09-24T05:33:51.430 に答える