To do this, you need to declare a merge driver :
This is the designated in .gitattributes , executed in the destination branch (the one where you do the merge)
echo yourFiles merge=addTheirs>.gitattributes git add .gitattributes git commit -m "record addTheirs merge driver"
(replace yourFiles with the file template you want to see in order to apply merge permission)
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 in addTheirs scripts called with %O , %A , %B (ancestor, ours, their)
A diff -u %A %B will provide you with hunks diff, for example:
@@ -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
Despite the lack of a diff header, patch will still be able to add new lines and delete the old one (and that you want to keep ours and add them).
On Windows, you can take gnu patch , but you need to add a manifest .
patch -u -p0 $3 $2
You can try to filter out the removal from the patch before applying it.
patch=$(diff -u $2 $3 | grep -v "^-")
But the hunk header ( @@ -1,11 +1,11 @@ ) will no longer match the expected number of lines (if you add only two lines and delete 0, it should end with +1,13 , nit +1,11 )
You need to process your patch to:
- filter deletion
- customize header headers
This means that addTheirs.sh (for placement anywhere on your path, even on Windows) can be:
#!/bin/bash patch=$(diff -u $2 $3) echo "${patch}" > f.pp patch2=$(./padd f.pp) echo "$patch2" > fp patch -u -p0 $2 -i fp
( diff is part of the 200+ unix command of the git-for-windows package command, so it all works on Windows or Unix)
The 'padd' utility (patch add) is a script to remove any delete line from each line and update the hunk header to track the actual line number.
I did mine in Go ( https://golang.org/ , just unzip the go distribution anywhere and add it to your PATH )
Copy the following into the padd.go file and enter go build padd.go : you will get a padd that can call the merge driver to configure 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 } }