在解决合并冲突时,Git可以自动处理插入吗?

And*_*eKR 6 git merge-conflict-resolution

在解决合并冲突时,大部分时间都是因为两个人插入文件的同一点.我总是这样做:使用左侧的新代码,从右侧复制新代码并在左侧代码后附加.

这让我感到疑惑,如果我总是这样做,应该可以实现自动化.我可以告诉Git相信这两个新块可以一个接一个地使用吗?

我认为,如果插入分开几行(Git自动解决的情况),那么引入错误的可能性就不会那么大.无论如何,我要检查结果.

(目前我使用DiffMerge作为我的mergetool,如果这有任何区别.)

Von*_*onC 9

您需要为此声明一个合并驱动程序:

这是.gitattributes目标分支(您正在进行合并的那个)中的 done中分配的

echo yourFiles merge=addTheirs>.gitattributes
git add .gitattributes
git commit -m "record addTheirs merge driver"
Run Code Online (Sandbox Code Playgroud)

(替换yourFiles为您希望看到应用合并分辨率的文件模式)

但它也需要在本地配置:

git config merge.addTheirs.name "keep additions only"
git config merge.addTheirs.driver addTheirs.sh
Run Code Online (Sandbox Code Playgroud)

诀窍是在addTheirs脚本,调用%O,%A,%B(祖先,我们的,他们的)

A diff -u %A %B会给你多样的差异:

@@ -1,11 +1,11 @@
 line 1
 line 2
-line 3 from master
+line 3 from dev
 line 4
 line 5
 line 6
 line 7
 line 8
+line 8bis from dev
 line 9
 line 10
-line 11
Run Code Online (Sandbox Code Playgroud)

即使缺少diff标头,patch仍然可以添加新行删除旧行(并且您想要保留我们的行,并添加它们).
在Windows上,您可以使用gnupatch,但需要添加清单.

patch -u -p0 $3 $2
Run Code Online (Sandbox Code Playgroud)

在应用补丁之前,您可以尝试过滤掉补丁中的删除.

patch=$(diff -u $2 $3 | grep -v "^-")
Run Code Online (Sandbox Code Playgroud)

但是hunk header(@@ -1,11 +1,11 @@)将不再匹配预期的行数(如果你只添加2行并删除0,它应该结束+1,13,nit +1,11)

您需要处理补丁以便:

  • 过滤掉删除
  • 调整大块头

这意味着addTheirs.sh(放在你的路径中的任何地方,即使在Windows上)可能是:

#!/bin/bash

patch=$(diff -u $2 $3) 
echo "${patch}" > f.pp

patch2=$(./padd f.pp)
echo "$patch2" > f.p

patch -u -p0 $2 -i f.p
Run Code Online (Sandbox Code Playgroud)

(diffgit-for-windows的200多个unix命令的一部分,所以再一次,所有这些都适用于Windows或Unix)

'padd'(补丁添加)实用程序是一个脚本,用于从每个块中删除任何删除行,并更新块头以跟踪实际行号.

我在Go中制作了我的(https://golang.org/,只需在任何你想要的地方解压缩发行版并将其添加到你的PATH)

将以下内容复制到padd.go文件中,然后键入go build padd.go:您将获得padd合并驱动程序可以调用的可执行文件以调整修补程序.

package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "regexp"
    "strconv"
    "strings"
)

// @@ 1,11 1,13 @@ <= extract prefix '@@ 1, 11 1,' and counter '13'
var chunkre = regexp.MustCompile(`(?m)^(@@.*,)(\d+)\s+@@.*$`)
var patch = ""

func main() {
    fname := os.Args[1]
    f := ""
    if b, err := ioutil.ReadFile(fname); err != nil {
        panic(err)
    } else {
        f = string(b)
    }
    lines := strings.Split(f, "\n")

    prefix := ""
    counter := 0
    var err error
    hunk := ""
    for _, line := range lines {
        snbadd := chunkre.FindAllStringSubmatch(line, -1)
        if len(snbadd) > 0 {
            updatePatch(hunk, prefix, counter)
            hunk = ""
            prefix = snbadd[0][1]
            if counter, err = strconv.Atoi(snbadd[0][2]); err != nil {
                panic(err)
            }
        } else if prefix != "" {
            if strings.HasPrefix(line, "-") {
                counter = counter + 1
                line = " " + line[1:]
            }
            hunk = hunk + line + "\n"
        }
    }
    updatePatch(hunk, prefix, counter)
    fmt.Println(patch)
}

func updatePatch(hunk, prefix string, counter int) {
    if hunk != "" {
        header := prefix + fmt.Sprintf("%d @@\n", counter)
        patch = patch + header + hunk
    }
}
Run Code Online (Sandbox Code Playgroud)