You would need to declare a merge driver for that:
This is assigned in a .gitattributes
done in the destination branch (the one where you are doing the merge)
echo yourFiles merge=addTheirs>.gitattributes
git add .gitattributes
git commit -m "record addTheirs merge driver"
(replace yourFiles
by the pattern of files you want to see that merge resolution applied)
But it also needs to be configured locally:
git config merge.addTheirs.name "keep additions only"
git config merge.addTheirs.driver addTheirs.sh
The trick is on the addTheirs
scripts, called with %O
, %A
, %B
(ancestor, ours, their)
A diff -u %A %B
will give you hunks of diff like:
@@ -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
Even though the diff header is missing, a patch
would still be able to add new lines and removes old one (and what you want is to keep ours, and add theirs).
On Windows, you can take a gnu patch
, but you need to add a manifest.
patch -u -p0 $3 $2
You could try to filter out the deletions from the patch before applying it.
patch=$(diff -u $2 $3 | grep -v "^-")
But the hunk header (@@ -1,11 +1,11 @@
) would no longer match the number of lines expected (if you only add 2 lines and removes 0, it should end with +1,13
, nit +1,11
)
You need to process your patch in order to:
- filter out the deletions
- adjust the hunk headers
That means the addTheirs.sh
(to put anywhere in your path, even on Windows) could be:
#!/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
(diff
is part of the 200+ unix commands part of the git-for-windows
package, so again, all of this works on Windows or on Unix)
The 'padd' (patch add) utility is a script removing any deletion line from each hunk, and updating the hunk header to keep track of the actual line number.
I made mine in Go (https://golang.org/, simply unzip a go distro anywhere you want and add it to your PATH
)
Copy the following in a padd.go
file, and type go build padd.go
: you get the padd
executable that the merge driver can call to adjust the patch.
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
}
}