git和append-mostly文件的策略

its*_*dok 26 git git-merge

我的存储库中有一些文件是底层增长的:大多数更改都涉及在文件底部添加新行.这主要是语言和其他属性文件.

作为一个恼人的副作用,每当两个人同时添加时,我就会遇到合并冲突,并且解决方案总是涉及手动复制粘贴,以便包含来自两个版本的行.

是否有一个提示,技巧或方法可以减轻这个过程中的一些痛苦?

例如,一个简单的解决方案是告诉开发人员在文件中间的随机位置添加新行.这可能会奏效,但它涉及到有意识的努力,以及一个奇怪的历史.

Von*_*onC 17

您可以使用gitattributes机制来定义自定义合并驱动程序(例如此类驱动程序),以便自动复制相关部分.

[merge "aggregate"]
        name = agregate both new sections
        driver = aggregate.sh %O %A %B
Run Code Online (Sandbox Code Playgroud)

这将是一个3路合并,这意味着你可以轻松地差异%A%B%O(共同的祖先),以隔离说新的章节,并聚集在他们的结果合并的文件.

聚合合并驱动程序只需要:

comm -13 $1 $3 >> $2
Run Code Online (Sandbox Code Playgroud)

(如果你在Windows上,comm实用程序是Windows上的GoW - Gnu的一部分- 分发)


这是一个小小的演示:

首先,让我们设置一个Git仓库,在两个分支(' master'和' abranch')中修改一个文件:

C:\prog\git\tests>mkdir agg
C:\prog\git\tests>cd agg
C:\prog\git\tests\agg>git init r1
Initialized empty Git repository in C:/prog/git/tests/agg/r1/.git/
C:\prog\git\tests\agg>cd r1

# Who am I?
C:\prog\git\tests\agg\r1>git config user.name VonC
C:\prog\git\tests\agg\r1>git config user.email vonc@xxx

# one file, first commit:
C:\prog\git\tests\agg\r1>echo test > test.txt
C:\prog\git\tests\agg\r1>git add .
C:\prog\git\tests\agg\r1>git commit -m "first commit"
[master c34668d] first commit
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt

# Let's add one more common line:
C:\prog\git\tests\agg\r1>echo base >> test.txt
C:\prog\git\tests\agg\r1>more test.txt
test
base
C:\prog\git\tests\agg\r1>git add .
C:\prog\git\tests\agg\r1>git commit -m "base"
[master d1cde8d] base
 1 file changed, 1 insertion(+)
Run Code Online (Sandbox Code Playgroud)

现在我们创建一个新的分支,并在该文件的两个版本中进行并发修改,就像OP itsadok在问题中指定的那样.

C:\prog\git\tests\agg\r1>git checkout -b abranch
Switched to a new branch 'abranch'
C:\prog\git\tests\agg\r1>echo "modif from abranch" >> test.txt
C:\prog\git\tests\agg\r1>git add .
C:\prog\git\tests\agg\r1>git commit -m "abranch contrib"
[abranch a4d2632] abranch contrib
 1 file changed, 1 insertion(+)
C:\prog\git\tests\agg\r1>type test.txt
test
base
"modif from abranch"

# back to master
C:\prog\git\tests\agg\r1>git checkout master
Switched to branch 'master'
C:\prog\git\tests\agg\r1>echo "contrib from master" >> test.txt
C:\prog\git\tests\agg\r1>git add .
C:\prog\git\tests\agg\r1>git commit -m "contrib from master"
[master 45bec4d] contrib from master
 1 file changed, 1 insertion(+)
C:\prog\git\tests\agg\r1>type test.txt
test
base
"contrib from master"
Run Code Online (Sandbox Code Playgroud)

我们有两个分支(注意:git lg是我的别名)

C:\prog\git\tests\agg\r1>git lg
* 45bec4d - (HEAD, master) contrib from master (86 minutes ago) VonC
| * a4d2632 - (abranch) abranch contrib (86 minutes ago) VonC
|/
* d1cde8d - base (87 minutes ago) VonC
* c34668d - first commit (89 minutes ago) VonC
Run Code Online (Sandbox Code Playgroud)

现在让我们尝试合并:

C:\prog\git\tests\agg\r1>git merge abranch
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.

C:\prog\git\tests\agg\r1>more test.txt
test
base
<<<<<<< HEAD
"contrib from master"
=======
"modif from abranch"
>>>>>>> abranch
Run Code Online (Sandbox Code Playgroud)

......宣告失败;)A git merge --abort将重置情况.

让我们合并驱动程序:

C:\prog\git\tests\agg\r1>git config merge.aggregate.name "aggregate both new sections"
C:\prog\git\tests\agg\r1>git config merge.aggregate.driver "aggregate.sh %O %A %B"
C:\prog\git\tests\agg\r1>echo test.txt merge=aggregate > .gitattributes
Run Code Online (Sandbox Code Playgroud)

此时,合并仍然失败:

C:\prog\git\tests\agg\r1>git merge abranch
aggregate.sh .merge_file_a09308 .merge_file_b09308 .merge_file_c09308: aggregate.sh: command not found
fatal: Failed to execute internal merge
Run Code Online (Sandbox Code Playgroud)

正常:我们需要编写该脚本,并将其添加到PATH:

vim aggregate.sh:
#!/bin/bash

# echo O: $1
# echo A: $2
# echo B: $3

# After http://serverfault.com/q/68684/783
# How can I get diff to show only added and deleted lines?
# On Windows, install GoW (https://github.com/bmatzelle/gow/wiki/)
ob=$(comm -13 $1 $3)
# echo "ob: ${ob}"

echo ${ob} >> $2

----

C:\prog\git\tests\agg\r1>set PATH=%PATH%;C:\prog\git\tests\agg\r1
Run Code Online (Sandbox Code Playgroud)

而现在,aggregate合并司机可以操作:

C:\prog\git\tests\agg\r1>git merge --no-commit abranch
Auto-merging test.txt
Automatic merge went well; stopped before committing as requested

C:\prog\git\tests\agg\r1>type test.txt
test
base
"contrib from master"
"modif from abranch"
Run Code Online (Sandbox Code Playgroud)

在这里你去:test.txt文件的结尾abranch已添加到文件中master.


gio*_*ele 5

另一种解决方案是使用--unionplumbing命令的选项git-merge-file

[merge "aggregate"]
    name = aggregate both new sections
    driver = git merge-file --union -L %P %A %O %B
Run Code Online (Sandbox Code Playgroud)

这比使用更可靠commcomm当输入线没有根据排序时,可能产生错误的输出LC_COLLATE

  • 我认为你可以在不添加自定义合并策略的情况下获得相同的结果,只需在 `.gitattributes` 中设置 `myfile merge=union` https://about.gitlab.com/2015/02/10/gitlab-reduced-merge-conflicts -by-90-percent-with-changelog-placeholders/ (2认同)