git-mergeが行末の違いを無視することは可能ですか?


150

git merge行末の違いを無視することは可能ですか?

たぶん私は間違った質問をしています...しかし:

私は試してみましたconfig.crlf inputが、特に事後に適用しときに、物事は少し乱雑で制御不能になりました

1つには、事後にこの構成を適用しても、このオプションを適用する前にリポジトリにコミットされたファイルには影響がないようです。もう1つは、突然すべてのコミットがCRLFがLFに変換されることに関する多くの迷惑な警告メッセージが発生することです。

正直なところ、どの行末が使用されているかは気にしません\n。個人的にはUnixスタイルを好みますが、何でもかまいません。私が気にしgit mergeているのは、少し賢く、行末の違いを無視することです。

時々私は2つの同じファイルを持っていますが、gitはそれらが異なる行末文字を使用しているという理由だけで競合しているとマークします(そして競合はファイル全体です)。

更新:

オプションをgit diff受け入れることがわかりましたが--ignore-space-at-eolgit mergeこのオプションも使用できるようにすることは可能ですか?


28
ああ。gitのこの行の終わりは完全に壊れています
1800情報

サードパーティのマージツールがマージ中にeolスタイルを無視することを示すテストケースを追加しました
VonC '14年

だから、(私が判断できることから)明確にするために:gitにCRを無視させ、他のすべての末尾の空白について文句を言う方法はありませんか?
スティーブン

以下の回答を必ずgit config merge.renormalize true
ご覧ください

回答:


115

2013年更新:

より最近のgitバージョンは、ストラテジーrecursiveとストラテジーオプションとのマージを使用して認証します-X):

git merge -s recursive -Xignore-space-at-eol

ただし、「-Xignore-space-change」の使用も可能です


jakub.gはまた、戦略はチェリーピッキングでも機能することをコメントしています

git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize 

これはに比べてはるかにうまく機能しignore-all-spaceます。


元の回答(2009年5月)

2007年6月に eolスタイルを無視するためのパッチが提案されましたが、それは懸念事項でありgit diff --ignore-space-at-eol、懸念事項ではありませんgit merge

当時、質問はされていました:

--ignore-space-at-eolオプションにする必要がありますgit-mergeか?
この機能が重要なのはマージです。
これらのオプションが有効になっている自動解決されたマージのセマンティクスは何ですか?それらは名前の変更の検出にのみ使用されますか?たとえば、空白の変更のみとの競合にフラグを立てませんか?そうでない場合、どのバージョンを自動的に受け入れますか?

フリオC浜野は熱狂的ではなかった。

これは確かに魅力的ですが、それは後のラウンドに任せるべきだと私は思います。
私はそれが2つの異なる種類の差分の概念を導入するのではないかと思います。1つは機械的に処理されます(つまり、 "git-merge-recursive"とのマージで使用され、 "git-am"で適用されます)。理解する人間。
変更された入力ファイルの比較からの出力が機械的アプリケーションに容易に使用できない場合でも、後者の場合は入力を変更することが役立つ場合があります。

一般的なアイデアgit mergeは、サードパーティのマージツールに依存することです。

たとえば、DiffMergeをGitマージ用のツールとして設定し、そのマージツールが特定のタイプのファイルのEOLを無視できるようにするルールセットを設定しました。


DOSまたはGit bashセッション用のMSysGit1.6.3を使用し、DiffMergeまたはKDiff3を使用するWindowsでのセットアップ:

  • PATHにディレクトリを設定します(ここでは:)c:\HOMEWARE\cmd
  • そのディレクトリにスクリプトmerge.sh(お気に入りのマージツールのラッパー)を追加します。

merge.sh:

#!/bin/sh

# Passing the following parameters to mergetool:
#  local base remote merge_result

alocal=$1
base=$2
remote=$3
result=$4

if [ -f $base ]
then
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$base" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # for merge respecting eol, KDiff3 is better than DiffMerge (which will always convert LF into CRLF)
    # KDiff3 will display eol choices (if Windows: CRLF, if Unix LF)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$alocal" "$remote" -o "$result"
else
    #there is not always a common ancestor: DiffMerge needing 3 files, BASE will be the result
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$result" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # KDiff3 however does know how to merge based on 2 files (not just 3)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$remote" -o "$result"
fi
  • Gitのマージラッパーを宣言する

Git configコマンド:

git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd "merge.sh \"$PWD/$LOCAL\" \"$PWD/$BASE\" \"$PWD/$REMOTE\" \"$PWD/$MERGED\"
git config --global mergetool.diffmerge.trustExitCode false
git config --global mergetool.diffmerge.keepBackup false
  • autoCRLFがfalseであることを確認します

システムレベルでのgit設定:

git config ---system core.autoCRLF=false
  • 2つの行が同一(ただしそれらのeol文字)の場合、DiffMergeまたはKDiff3の両方がマージ中にそれらの行を無視することをテストします。

DOSスクリプト(注:dos2unixコマンドはここから取得され、Unix eolスタイルをシミュレートするために使用されます。このコマンドは、この回答の冒頭で言及されたディレクトリにコピーされています。):

C:\HOMEWARE\git\test>mkdir test_merge C:\HOMEWARE\git\test>cd test_merge C:\HOMEWARE\git\test\test_merge>git init C:\HOMEWARE\git\test\test_merge>echo a1 > a.txt & echo a2 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "a.txt, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout -b windows Switched to a new branch 'windows' C:\HOMEWARE\git\test\test_merge>echo a3 >> a.txt & echo a4 >> a.txt C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add two lines, windows eol style" C:\HOMEWARE\git\test\test_merge>git checkout master C:\HOMEWARE\git\test\test_merge>git checkout -b unix Switched to a new branch 'unix' C:\HOMEWARE\git\test\test_merge>echo au3 >> a.txt & echo au4 >> a.txt && echo au5 >> a.txt C:\HOMEWARE\git\test\test_merge>dos2unix a.txt Dos2Unix: Processing file a.txt ... C:\HOMEWARE\git\test\test_merge>git add a.txt C:\HOMEWARE\git\test\test_merge>git commit -m "add 3 lines, all file unix eol style" [unix c433a63] add 3 lines, all file unix eol style C:\HOMEWARE\git\test\test_merge>git merge windows Auto-merging a.txt CONFLICT (content): Merge conflict in a.txt Automatic merge failed; fix conflicts and then commit the result. C:\HOMEWARE\git\test\test_merge>git ls-files -u 100644 39b4c894078a02afb9b1dfeda6f1127c138e38df 1 a.txt 100644 28b3d018872c08b0696764118b76dd3d0b448fca 2 a.txt 100644 3994da66530b4df80189bb198dcfac9b8f2a7b33 3 a.txt C:\HOMEWARE\git\test\test_merge>git mergetool Merging the files: a.txt Normal merge conflict for 'a.txt': {local}: modified {remote}: modified Hit return to start merge resolution tool (diffmerge):

この時点で(「return」を非表示にします)、DiffMergeまたはKDiff3が開き、実際にマージされている行と無視されている行が表示されます。

警告:結果ファイルは常にDiffMergeを使用したWindows eolモード(CRLF)になります...
KDiff3は何らかの方法で保存を提供します。


先端をありがとう!MacのMeldとFileMergeも素晴らしいアプリのようです。
レオ・レオポルド・ヘルツ준 영

1
git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalizeignore-all-space
ちなみに

1
@ jakub.g良い点!私はより多くの可視性のために答えにそれを含めました。
VonC 2014年

98

私は同じ答えを探していて、これを見つけました

異なるチェックイン/チェックアウト属性を持つブランチをマージする

clean / smudgeフィルターやtext / eol / ident属性の追加など、ファイルの正規リポジトリ形式を変更させる属性をファイルに追加した場合、属性が配置されていない場所をマージすると、通常はマージの競合が発生します。 。

これらの不要なマージの競合を防ぐために、3方向のマージを解決するときに、merge.renormalize構成変数を設定して、ファイルの3つのステージすべての仮想チェックアウトとチェックインを実行するようにgitに指示できます。これにより、変換されたファイルが未変換のファイルとマージされるときに、チェックイン変換によって引き起こされる変更が誤ったマージの競合を引き起こすのを防ぎます。

「smudge→clean」の結果がすでに汚されているファイルでも「clean」と同じ出力になる限り、この戦略はすべてのフィルター関連の競合を自動的に解決します。このように機能しないフィルターは、手動で解決する必要がある追加のマージ競合を引き起こす可能性があります。

したがって、任意のリポジトリでこのコマンドを実行すると、トリックが実行されます。

git config merge.renormalize true

20
これがデフォルトの答えに値するはずです。質問が最初に尋ねられてから多くの変更があり、gitのこれの処理は、あなたが言うように、merge.renormalizeに組み込まれています。
アントンI.シポス

これはすごいです。私の日を節約します
matthaeus



4

私がしたことは、すべてをデフォルトのままにして(つまり、autocrlf = true)、すべてのファイルをタッチし(。-exec touch {} \;を検索)、gitがそれらを「変更済み」として認識し、コミットして戻すことでした。そうしないと、迷惑なメッセージや意外な違いに常に悩まされるか、gitのすべての空白機能をオフにする必要があります。

非難情報は失われますが、後で行うよりも早く行うことをお勧めします:)





0

今では、マージする前に両方のブランチ(およびコミット)の行末を正規化するのが最善の方法であるように思えます。

私は「convert crlf to lf」をググって、これを最初の結果として見つけました:http ://stahlforce.com/dev/index.php?tool=remcrlf

私はそれをダウンロードして使用しましたが、素晴らしいツールのようです。

>sfk remcr . .py

ただし、ディレクトリとファイルタイプ(例:.py)を指定してください。指定しないと、.gitディレクトリの内容が乱れる可能性があります。


0

AFAICT、(私は試していませんが)git diffマージするブランチを共通の祖先と比較するために使用でき、その結果をで適用できますgit apply。どちらのコマンドにも --ignore-whitespace行末エラーと空白エラーを無視するオプションあります。

残念ながら、パッチが正しく適用されない場合、操作全体が中止されます。マージの競合を修正することはできません。ファイルに--rejectパッチ不可能なハンクを残すオプションがあり.rejます。これは役立ちますが、1つのファイルにマージの競合が表示されるのと同じではありません。


-1

マージ競合の解決を読んだ後:すべてのファイルを強制的に上書きする

この問題のバージョンをようやく解決しました。アップストリームリポジトリから更新をプルしようとしましたが、現在のリポジトリにはCRLF関連の問題があり、結果としてマージできませんでした。心配する必要のあるローカルな変更はありませんでした。次の手順で問題が解決しました:

フォークの同期に関するgithubの指示に従って(https://help.github.com/articles/syncing-a-fork/):

  1. git fetch upstream

  2. git reset --hard upstream/master
    gitについての私の限られた理解は、これが私がやりたいことをしていることを教えてくれます-アップストリームソースに加えられたすべての変更を取得するために(実際のコミットされていない変更なしで)フォークをリベースします。ソースページによると、この手順は通常は必要ないはずですが、CRLFの問題により必要になりました。

  3. git merge upstream/master

  4. git push

1
あなたはそれgit reset --hard upstream/masterがあなたのローカルブランチを捨ててそれをupstream/masterにポイントしgit merge upstream/master、何もしないことに気づいていますか?
ChristofferHammarström2015年

-1

ただし、私はsedなどのツールを使用して正しい行末を取得し、ファイルを比較することをお勧めします。私は数時間を差分に費やしましたさまざまなプロジェクトの。

最善の方法は:

  1. プロジェクトファイルのみをコピー(省略 .gitディレクトリを)を別のディレクトリにし、その中にリポジトリを作成してから、ファイルを追加してコミットします(新しいリポジトリのマスターブランチにある必要があります)。
  2. 2番目のプロジェクトから同じフォルダーにファイルをコピーしますが、たとえば別のブランチdevgit checkout -b dev)、このブランチでファイルをコミットして実行(最初のプロジェクトがマスターにある場合): git diff master..dev --names-only 変更されたファイルの名前のみを表示します
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.