2015-06-23 17 views
6

Khi giải quyết xung đột hợp nhất, phần lớn thời gian là do hai người được chèn vào cùng một điểm của một tệp. Và tôi luôn làm như vậy: Sử dụng mã mới từ phía bên trái, sao chép mã mới từ phía bên phải và thêm mã sau mã từ phía bên trái.Git có thể tự động xử lý chèn khi giải quyết xung đột hợp nhất không?

Điều này khiến tôi băn khoăn, nếu tôi luôn làm như vậy, bạn có thể tự động hóa việc này. Tôi có thể nói với Git tin tưởng rằng cả hai khối mới có thể được sử dụng sau cái kia?

Tôi nghĩ rằng, nếu chèn sẽ là một vài dòng ngoài (một tình huống Git tự động giải quyết), nó sẽ không có bất kỳ ít khả năng để giới thiệu lỗi. Tôi sẽ kiểm tra kết quả anyway.

(Hiện nay tôi đang sử dụng DiffMerge như mergetool của tôi, nếu mà làm cho bất kỳ sự khác biệt.)

+0

Điều gì sẽ xảy ra nếu bạn có hai chi nhánh, một nhánh giới thiệu câu lệnh 'return 1;' và câu lệnh khác đã giới thiệu câu lệnh 'return -1;'? Tôi sẽ lập luận rằng chỉ một (nếu có) của những người có thể là chính xác, và rằng chỉ cần ghép hai là chính xác là điều sai trái để làm. Việc hợp nhất chính xác trong tất cả các trường hợp tầm thường đòi hỏi phải có suy nghĩ thực tế để thực hiện chính xác, và nói chung yêu cầu rằng việc sáp nhập có một sự hiểu biết tốt về những gì mã xung quanh được cho là đang thực hiện, để đưa ra quyết định thông minh ... – twalberg

+1

Sự tồn tại của những thứ như [Semantic Merge] (https://www.semanticmerge.com/) là bằng chứng cho thấy việc sáp nhập các thay đổi trong một tệp đơn lẻ nói chung là không tầm thường. – poke

+1

@twalberg Nếu hai trở về sẽ ở trong cùng một chức năng nhưng một vài dòng ngoài, Git sẽ hợp nhất chúng tốt và tôi dám nói rằng đó là bằng nhau có khả năng để intruduce một lỗi. Thời gian tôi tiết kiệm được bằng cách không phải hợp nhất chúng một cách man rợ mà tôi có thể chi trả cho việc kiểm tra hai lần mọi ý nghĩa ngữ nghĩa. – AndreKR

Trả lời

9

Bạn sẽ cần phải declare a merge driver cho rằng:

này được assigned in a .gitattributes thực hiện tại các chi nhánh đích (một trong những nơi bạn đang làm việc hợp nhất)

echo yourFiles merge=addTheirs>.gitattributes 
git add .gitattributes 
git commit -m "record addTheirs merge driver" 

(thay thế yourFiles bởi các mô hình của các tập tin bạn muốn để thấy rằng độ phân giải hợp nhất áp dụng)

Nhưng nó cũng cần phải được cấu hình địa phương:

git config merge.addTheirs.name "keep additions only" 
git config merge.addTheirs.driver addTheirs.sh 

Bí quyết là trên addTheirs kịch bản, gọi với %O, %A, %B (tổ tiên, chúng ta, họ)

Một diff -u %A %B sẽ cung cấp cho bạn hunks của diff như:

@@ -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 

Mặc dù tiêu đề khác bị thiếu, patch vẫn có thể thêm các dòng mới xóa một thẻ cũ (và những gì bạn muốn là giữ của chúng tôi và thêm chúng).
Trên Windows, bạn có thể chụp gnu patch, but you need to add a manifest.

patch -u -p0 $3 $2 

Bạn có thể thử để lọc ra các trang bị xóa từ các bản vá trước khi áp dụng nó.

patch=$(diff -u $2 $3 | grep -v "^-") 

Nhưng header hunk (@@ -1,11 +1,11 @@) sẽ không còn phù hợp với số dòng dự kiến ​​(nếu bạn chỉ thêm 2 dây chuyền và loại bỏ 0, nó nên kết thúc với +1,13, nit +1,11)

Bạn cần phải xử lý bản vá của bạn để:

  • lọc ra các trang bị xóa
  • điều chỉnh tiêu đề hunk

đó có nghĩa là addTheirs.sh (đặt bất cứ nơi nào trong đường dẫn của bạn, ngay cả trên Windows) có thể là:

#!/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 là một phần của hơn 200 unix lệnh một phần của git-for-windows package, vì vậy một lần nữa, tất cả các điều này hoạt động trên Windows hoặc trên Unix)

Tiện ích 'padd' (bản vá thêm) là một tập lệnh xóa mọi dòng xóa khỏi mỗi đoạn, và cập nhật tiêu đề hunk để theo dõi số dòng thực.

tôi làm mỏ tại Gò (https://golang.org/, chỉ cần unzip a go distro bất cứ nơi nào bạn muốn và thêm nó vào bạn PATH)

Sao chép sau đây trong một tập tin padd.go, và gõ go build padd.go: bạn sẽ có được padd thực thi mà người lái xe hợp nhất có thể gọi để điều chỉnh miếng vá.

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+)\[email protected]@.*$`) 
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 
    } 
} 
+0

Ok, tôi đã tạo một tệp, cam kết làm chủ, thêm dòng và thay đổi dòng khác, cam kết, quay lại, thêm một dòng khác vào cùng một vị trí và thay đổi cùng một dòng khác nhau, cam kết chi nhánh "test", sau đó sử dụng phương pháp của bạn để hợp nhất "test" thành "master". Trong thực tế, cả hai xung đột đã được giải quyết tự động, nhưng bây giờ nó giống hệt với phiên bản trong "master". Đã xảy ra lỗi: http://pastebin.com/U3ADUVjv – AndreKR

+0

@AndreKR nội dung của f.p và f.pp là gì? – VonC

+0

Một dòng mới (0x0A) trong cả hai tệp. – AndreKR

Các vấn đề liên quan