git 병합 충돌을 설명하기 위해 비슷한 의미를 갖는 두 개의 git 기반이 아닌 텍스트 파일을 병합합니다.

git 병합 충돌을 설명하기 위해 비슷한 의미를 갖는 두 개의 git 기반이 아닌 텍스트 파일을 병합합니다.

git"병합 충돌"이 설명되는 방식 과 유사한 의미를 사용하여 git기반이 아닌 두 개의 텍스트 파일을 병합 하고 싶습니다 .

file.1예를 들어, 이름이 비슷 하지만 내용이 동일하지 않은 두 개의 텍스트 파일이 있다고 가정해 보겠습니다 file.2. 이 두 파일을 다음과 같이 세 번째 파일로 병합하고 싶습니다.

hypothetical-merge-utility file.1 file.2 file.merged

file.merged다음과 유사한 방식으로 파일 내용과 각 차이점을 나열하는 생성을 원합니다 .

common line 1 ...
common line 2 ...
common line 3 ...
<<<<<<< file.1
something unique from file.1
a second line of something unique from file.1
======= file.2
something unique from file.2
>>>>>>> end of diff
common line 4 ...
common line 5 ...
<<<<<<< file.1
something unique from file.1
======= file.2
something unique from file.2
a second line of something unique from file.2
>>>>>>> end of diff
common line 6 ...
common line 7 ...
... etc. ...

즉, file.1와 사이의 모든 차이점이 file.2"병합 충돌"의 표현과 유사하게 나타나기를 원합니다 git.

<<<<<<<<, , 및 ========이외의 구분 기호를 사용해도 상관 없습니다 .>>>>>>>>

Linux에는 텍스트 파일을 병합하는 데 사용할 수 있는 유틸리티가 많이 있다는 것을 알고 있습니다. 그러나 나는오직git"병합 충돌"이 설명되는 방식과 유사한 방식으로 병합된 데이터를 구체적으로 나타내는 콘텐츠를 찾으세요.

그러한 유틸리티에 대해 아는 사람이 있습니까?

미리 감사드립니다.

고쳐 쓰다: Ed Morton의 다음 질문을 바탕으로 두 테스트 파일의 내용은 다음과 같습니다.

==== 파일.1 ====

common line 1 ...
common line 2 ...
common line 3 ...
something unique from file.1
a second line of something unique from file.1
common line 4 ...
common line 5 ...
something unique from file.1
common line 6 ...
common line 7 ...

==== 파일.2 ====

common line 1 ...
common line 2 ...
common line 3 ...
something unique from file.2
common line 4 ...
common line 5 ...
something unique from file.2
a second line of something unique from file.2
common line 6 ...
common line 7 ...

답변1

노트: 이것이 다소 합리적인 "답변"이라고 생각하지만 이제 더 나은 또 다른 "답변"을 생각해 냈습니다. 아래의 다른 "답변"을 참조하십시오.

이 "답변"의 원본 버전은...

오! 여기에 글을 올리기엔 너무 이르네요. -D명령줄 옵션을 몰랐 diff는데 이제 이걸 할 수 있다는 걸 깨달았습니다...

diff -D file.1 file.2 >file.merged

그것은 다음을 생산할 것입니다 file.merged...

common line 1 ...
common line 2 ...
common line 3 ...
#ifdef file.1
something unique from file.1
a second line of something unique from file.1
#else /* file.1 */
something unique from file.2
#endif /* file.1 */
common line 4 ...
common line 5 ...
#ifdef file.1
something unique from file.1
#else /* file.1 */
something unique from file.2
a second line of something unique from file.2
#endif /* file.1 */
common line 6 ...
common line 7 ...
... etc. ...

내가 감당할 수 있고 #ifdef, #elseOK , 내가 감당할 수 있는 #endif것처럼 git, <<<<<<<<OK .========>>>>>>>>

고쳐 쓰다:...방금 이걸 찾았어요: https://stackoverflow.com/questions/16902001/manually-merge-two-files-using-diff

통합 diff 형식을 사용하여 비슷한 작업을 수행할 수 있는 방법도 보여줍니다. 합계의 최대 행 수 보다 큰 인수를 갖는 옵션을 diff제공 합니다 . 예를 들어...-Ufile.1file.2

diff -U 99999999 file.1 file.2 | tail -n +4 >file.merged

그러면 다음과 같은 결과가 생성됩니다.

 common line 1 ...
 common line 2 ...
 common line 3 ...
+something unique from file.2
-something unique from file.1
-a second line of something unique from file.1
 common line 4 ...
 common line 5 ...
+something unique from file.2
+a second line of something unique from file.2
-something unique from file.1
 common line 6 ...
 common line 7 ...
 ... etc. ...

선은 +의 고유 데이터를 나타내고 file.2, -선은 의 고유 데이터를 나타냅니다 file.1.

나는 그것 +-라인을 처리할 수 있습니다.

답변2

출력 형식에 별로 관심이 없는 것처럼 들리지만, 각 파일에서 어떤 줄이 나오는지 또는 어떤 줄이 공통되는지 식별하는 방법을 알고 싶을 뿐입니다. 이건 어때:

$ diff --old-line-format=$'-%l\n' --new-line-format=$'+%l\n' --unchanged-line-format=$'=%l\n' file.1 file.2
=common line 1 ...
=common line 2 ...
=common line 3 ...
-something unique from file.1
-a second line of something unique from file.1
+something unique from file.2
=common line 4 ...
=common line 5 ...
-something unique from file.1
+something unique from file.2
+a second line of something unique from file.2
=common line 6 ...
=common line 7 ...

해당 행에 대한 소스 표시기를 얻기 위해 행의 내용을 테스트해야 하는 솔루션에 주의하세요(예: <<<<<<< file.1무엇이 고유한지 알려고 하는 경우 file1- file해당 문자열과 정확히 동일한 행이 포함되어 있으면 어떻게 됩니까?). 항상 발생합니다. 해당 문자열이 입력에 나타날 가능성이 있는 경우 모든 문자열에 대한 테스트가 실패하므로 각 줄의 고유한 위치를 나타내는 표시입니다. 위와 같이 첫 번째 문자는 항상 줄의 출처를 나타내므로 가능한 파일 내용과 충돌하지 않습니다. git merge 충돌의 정확한 출력 형식을 얻으려면(권장하지 않음) 위 내용을 인쇄하는 간단한 awk 스크립트로 파이프하거나 <<< file줄의 첫 번째 문자가 원하는 대로 변경될 때 항상 파이프할 수 있습니다. 해당 문자를 삭제하세요.

답변3

diff -D ...및 와 관련된 첫 번째 "답변"에 원래 게시한 솔루션의 제한으로 인해 Python 모듈을 사용하여 Python으로 솔루션을 작성하기 diff -U ...로 결정했습니다 .difflib

, , 와 같은 문자열을 포함하는 구분 기호를 git사용하는데 , 알고 있듯이 원본 텍스트에 이와 같은 문자열이 포함되어 있으면 모호함이 발생할 수 있습니다. 그러나 의 "병합 충돌" 출력에도 동일한 모호성이 존재할 수 있지만 나는 그것에 만족 하고 기꺼이 함께 살기 때문에 내 솔루션의 이러한 모호성에도 만족합니다.<<<<<<<<========>>>>>>>>gitgit

출력은 "병합 충돌" 출력과 정확히 동일하지는 않지만 git내가 원하는 만큼 충분합니다.

첫째, 여기에 Python 프로그램이 있습니다(여기에 게시한 원래 Python 코드를 정리했는데 이것이 정리된 버전입니다). 나는 이 프로그램을 호출합니다 filemerge...

#!/usr/bin/python3

### Take the diff's between two files and output
### the common and different lines in a manner
### which is very similar to the way that `git`
### depicts merge conflicts.

import sys
sys.dont_write_bytecode = True

import os

from difflib import unified_diff

prog       = None
diff_start = '<<<<<<<<'
diff_sep   = '========'
diff_end   = '>>>>>>>>'

def main():
    if len(sys.argv) < 3:
        print(f'\nusage: {prog} file1 file2\n')
        return 1

    file1, file2 = sys.argv[1:3]
    data1        = None
    data2        = None
    missing      = []

    try:
        with open(file1, 'r') as f:
            data1 = f.readlines()
    except Exception:
        missing.append(file1)

    try:
        with open(file2, 'r') as f:
            data2 = f.readlines()
    except Exception:
        missing.append(file2)
        
    if missing:
        print(f'\nnot found: {", ".join(missing)}\n')
        return 1

    n1 = len(data1)
    n2 = len(data2)
    max_lines = (n1 + 1) if n1 > n2 else (n2 + 1)
    count = 0
    state = ''
    sep_printed = False
    next_file = ''

    for line in unified_diff(data1, data2, n=max_lines):
        count += 1
        if count < 4:
            continue

        # Every line which is returned by unified_diff()
        # is at least 2 characters long. Each of these
        # lines starts with either ' ', '+', or '-', and
        # each of these lines ends with a newline.
        line = line[:-1]
        ch0  = line[0]

        if ch0 == ' ':
            if state:
                state = ''
                if not sep_printed:
                    print(f'{diff_sep}{next_file}')
                print(diff_end)
            sep_printed = False
            next_file = ''
        elif ch0 == '-':
            if state == ch0:
                pass
            elif state == '+':
                print(f'{diff_sep} file={file1}')
                sep_printed = True
                next_file = ''
            else:
                print(f'{diff_start} file={file1}')
                sep_printed = False
                next_file = f' file={file2}'
            state = ch0
        elif ch0 == '+':
            if state == ch0:
                pass
            elif state == '-':
                print(f'{diff_sep} file={file2}')
                sep_printed = True
                next_file = ''
            else:
                print(f'{diff_start} file={file2}')
                sep_printed = False
                next_file = f' file={file1}'
            state = ch0
        print(line[1:])

    if state:
        if not sep_printed:
            print(f'{diff_sep}{next_file}')
            next_file = ''
        print(diff_end)

    return 0

if __name__ == '__main__':
    prog = os.path.basename(sys.argv[0])
    sys.exit(main())

이것은 테스트에 사용한 입력 파일입니다. 원래 질문에 게시한 입력 파일과 유사하지만 정확히 동일하지는 않습니다...

file.1========

common line 1 ...
common line 2 ...
common line 3 ...
something unique from file.1
a second line of something unique from file.1
common line 4 ...
common line 5 ...
something unique from file.1
common line 6 ...
common line 7 ...
penultimate file.1 line
common line 8 ...

file.2========

common line 1 ...
second line from file.2
common line 2 ...
common line 3 ...
something unique from file.2
common line 4 ...
common line 5 ...
something unique from file.2
a second line of something unique from file.2
common line 6 ...
common line 7 ...
common line 8 ...

이렇게 명령어를 실행하는데...

filemerge file.1 file.2 >file.merged

결과는 다음과 같습니다 file.merged...

common line 1 ...
<<<<<<<< file=file.2
second line from file.2
======== file=file.1
>>>>>>>>
common line 2 ...
common line 3 ...
<<<<<<<< file=file.1
something unique from file.1
a second line of something unique from file.1
======== file=file.2
something unique from file.2
>>>>>>>>
common line 4 ...
common line 5 ...
<<<<<<<< file=file.1
something unique from file.1
======== file=file.2
something unique from file.2
a second line of something unique from file.2
>>>>>>>>
common line 6 ...
common line 7 ...
<<<<<<<< file=file.1
penultimate file.1 line
======== file=file.2
>>>>>>>>
common line 8 ...

앞서 언급했듯이 이는 Merge Contributes 출력과 정확히 동일한 형식은 아니지만 git매우 유사하고 나에게는 충분히 유사합니다.

관련 정보