107

gitリポジトリを介して誰かと共同作業をしていて、外部からの変更を受け入れたくない特定のファイルがあるとします。

git pullするたびに競合するマージについて文句を言わないようにローカルリポジトリを設定する方法はありますか?このファイルをマージするときは、常にローカルバージョンを選択したいと思います。

4

3 に答える 3

145

構成ファイルの特定のインスタンスについて、私はRonの答えに同意します
。構成はワークスペースに対して「プライベート」である必要があります(したがって、「ファイルで宣言」のように「無視」され.gitignoreます)。トークン化された値
を含む 構成ファイルテンプレートと、そのファイルをプライベート(および無視された)構成ファイルに変換するスクリプトがある場合があります。config.template


ただし、その特定の発言は、より広範でより一般的な質問、つまりあなたの質問(!)には答えません。

特定のファイルで競合するマージに対して常にローカルバージョンを選択するようにgitに指示するにはどうすればよいですか?(任意のファイルまたはファイルのグループの場合)

この種のマージは「コピーマージ」であり、競合が発生した場合は常に「ours」または「theirs」バージョンのファイルをコピーします。

コメントのBrian Vandenbergが指摘しているように、' 'と' 'はここではマージに使用されます。 これらはリベースでは逆になります。リベース使用する""を参照してください。 )。ourstheirs
Why is the meaning of “ours” and “theirs” reversed with git-svngit rebase

「ファイル」(悪い例であるため、「構成」ファイルとは言えないファイル)の場合、マージによって呼び出されるカスタムスクリプトを使用してこれを実現します。カスタムマージドライバーを定義するgitattributes
を定義するため、Gitはそのスクリプトを呼び出します。

この場合、「カスタムマージドライバ」は非常に単純なスクリプトであり、基本的に現在のバージョンを変更しないため、常にローカルバージョンを選択できます。

IE。、Ciro Santilliが指摘したように:

echo 'path/to/file merge=ours' >> .gitattributes
git config --global merge.ours.driver true

単純なシナリオで、Windows上のmsysgit 1.6.3を使用して、単なるDOSセッションでテストしてみましょう。

cd f:\prog\git\test
mkdir copyMerge\dirWithConflicts
mkdir copyMerge\dirWithCopyMerge
cd copyMerge
git init
Initialized empty Git repository in F:/prog/git/test/copyMerge/.git/

次に、2つのファイルを作成します。どちらも競合しますが、マージ方法が異なります。

echo a > dirWithConflicts\a.txt
echo b > dirWithCopyMerge\b.txt
git add -A
git commit -m "first commit with 2 directories and 2 files"
[master (root-commit) 0adaf8e] first commit with 2 directories and 2 files

2つの異なるgitブランチの両方のファイルのコンテンツに「競合」を導入します。

git checkout -b myBranch
Switched to a new branch 'myBranch'
echo myLineForA >> dirWithConflicts\a.txt
echo myLineForB >> dirWithCopyMerge\b.txt
git add -A
git commit -m "add modification in myBranch"
[myBranch 97eac61] add modification in myBranch

git checkout master
Switched to branch 'master'
git checkout -b hisBranch
Switched to a new branch 'hisBranch'
echo hisLineForA >> dirWithConflicts\a.txt
echo hisLineForB >> dirWithCopyMerge\b.txt
git add -A
git commit -m "add modification in hisBranch"
[hisBranch 658c31c] add modification in hisBranch

それでは、「hisBranch」を「myBranch」にマージしてみましょう。

  • 競合するマージの手動解決
  • 自分のバージョンdirWithCopyMerge\b.txtを常に保持したい場合を除いて。b.txt

マージは' MyBranch'で行われるため、それに切り替えてgitattributes、マージ動作をカスタマイズする''ディレクティブを追加します。

git checkout myBranch
Switched to branch 'myBranch'
echo b.txt merge=keepMine > dirWithCopyMerge\.gitattributes
git config merge.keepMine.name "always keep mine during merge"
git config merge.keepMine.driver "keepMine.sh %O %A %B"
git add -A
git commit -m "prepare myBranch with .gitattributes merge strategy"
[myBranch ec202aa] prepare myBranch with .gitattributes merge strategy

ディレクトリに定義された.gitattributesファイルdirWithCopyMerge(マージが発生するブランチでのみ定義されます:)があり、マージドライバーを含むファイルがありますmyBranch.git\config

[merge "keepMine"]
        name = always keep mine during merge
        driver = keepMine.sh %O %A %B

keepMine.shをまだ定義しておらず、とにかくマージを起動する場合は、次のようになります。

git merge hisBranch
sh: keepMine.sh: command not found
fatal: Failed to execute internal merge
git st
# On branch myBranch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   dirWithConflicts/a.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

type dirWithConflicts\a.txt
a
<<<<<<< HEAD:dirWithConflicts/a.txt
myLineForA
=======
hisLineForA
>>>>>>> hisBranch:dirWithConflicts/a.txt

それは結構です:

  • a.txtマージする準備ができており、競合があります
  • b.txt.gitattributesマージドライバがそれを処理することになっているため(ディレクトリ内のファイル内のディレクティブのため)、まだ変更されていません。

keepMine.shあなたのどこでも定義してください%PATH%(または$PATH私たちのUnixの友人のために。私はもちろん両方を行います:私はVirtualBoxセッションでUbuntuセッションを持っています)

lrkwzがコメントし、 Gitのカスタマイズ-Git属性の「戦略のマージ」セクションで説明されているように、シェルスクリプトをシェルコマンドに置き換えることができます。true

git config merge.keepMine.driver true

ただし、一般的なケースでは、スクリプトファイルを定義できます。

keepMine.sh

# I want to keep MY version when there is a conflict
# Nothing to do: %A (the second parameter) already contains my version
# Just indicate the merge has been successfully "resolved" with the exit status
exit 0

(これは1つの単純なマージドライバーでした;)(その場合はさらに単純です)(true
のバージョンを保持したい場合は、exit 0行の前に追加してください:
cp -f $3 $2
それだけです。マージドライバーは、他のバージョンからのバージョンを保持しません。ブランチ、ローカルの変更をオーバーライドする)

それでは、最初からマージを再試行してみましょう。

git reset --hard
HEAD is now at ec202aa prepare myBranch with .gitattributes merge strategy

git merge hisBranch
Auto-merging dirWithConflicts/a.txt
CONFLICT (content): Merge conflict in dirWithConflicts/a.txt
Auto-merging dirWithCopyMerge/b.txt
Automatic merge failed; fix conflicts and then commit the result.

マージは失敗します... a.txtの場合のみ
a.txtを編集し、「hisBranch」からの行を残して、次のようにします。

git add -A
git commit -m "resolve a.txt by accepting hisBranch version"
[myBranch 77bc81f] resolve a.txt by accepting hisBranch version

このマージ中にb.txtが保持されていることを確認しましょう

type dirWithCopyMerge\b.txt
b
myLineForB

最後のコミットは完全なマージを表します。

git show -v 77bc81f5e
commit 77bc81f5ed585f90fc1ca5e2e1ddef24a6913a1d
Merge: ec202aa 658c31c
git merge hisBranch
Already up-to-date.

(Mergeで始まる行はそれを証明しています)


Gitが行うように、マージドライバーを定義、結合、および/または上書きできることを考慮してください。

  • 調べる<dir>/.gitattributes(問題のパスと同じディレクトリにあります):ディレクトリ内の他.gitattributesのディレクトリに優先します
  • 次に、.gitattributes(親ディレクトリにある)を調べ、まだ設定されていない場合にのみディレクティブを設定します
  • 最後に調べます$GIT_DIR/info/attributes。このファイルは、ツリー内の設定を上書きするために使用されます。<dir>/.gitattributesディレクティブを上書きします。

「組み合わせる」とは、複数のマージドライバーを「集約する」ことを意味します。
Nick Greenは、コメントで、実際にマージドライバーを結合しようとしています。「 Pythongitドライバーを介してpomをマージする」を参照してください。
ただし、彼の他の質問で述べたように、競合(両方のブランチでの同時変更)の場合にのみ機能します。

于 2009-05-30T20:12:53.687 に答える
6

.gitattributes@ ciro-santilliがコメントしているように、設定で使用する簡単な方法は次のとおりです。

path/to/file merge=ours

次の方法でこの戦略を有効にします。

git config --global merge.ours.driver true

(私はこれをより見やすくするための答えとして追加していますが、ユーザーのクレジットを超えないようにコミュニティWikiにします。ここのQの下で彼のコメントに賛成してください!)

于 2019-12-27T16:27:51.610 に答える
0

上書きしたくない複数の構成ファイルがあります。ただし、.gitignoreと.gitattributesはこの状況では機能しませんでした。私たちの解決策は、構成ファイルをconfigsブランチに保存することでした。次に、gitマージ中にファイルを変更できるようにしますが、マージの直後に「gitcheckoutブランチ-」を使用します。マージするたびに、configsブランチからconfigファイルをコピーします。 詳細なstackoverflowの回答はこちら

于 2016-10-17T23:07:28.173 に答える