2013-10-17 15 views
12

Tôi có yêu cầu kéo mà Github cho biết nó không thể tự động hợp nhất. Sự thay đổi này là đằng sau chủ một vài cam kết, nhưng không có xung đột.Github không thể hợp nhất nhánh, không có xung đột, theo cách thủ công, nó tự động hợp nhất

thủ sáp nhập tôi không nhận được bất kỳ xung đột, và tôi nhận được kết quả này:

(on master) 
$git merge otherbranch 
[vim pops up for commit message, :wq] 
Auto-merging <file> 
Merge made by the 'recursive' strategy. 
<file> | 1 + 
1 file changed, 1 insertion(+) 

Có phải đó là lý do tại sao Github không thể hợp nhất tự động? Nó vẫn tự động sáp nhập từ dòng lệnh. Đây có phải là không đủ tự động cho Github?

Trả lời

12

Lý do là git merge sử dụng chiến lược được gọi là "đệ quy" hợp nhất theo mặc định. Nó có thể thực hiện hợp nhất 3 chiều: lấy miếng vá từ một phía, và áp dụng miếng vá đó sang phía bên kia, để tạo ra một tập tin mới. Nó cũng thực hiện điều này một cách đệ quy, trong các tình huống phức tạp hơn, nơi có nhiều phân nhánh và hợp nhất đã xảy ra và có nhiều cơ sở hợp nhất cho hai cam kết được sáp nhập.

Gần đây tôi đã gặp phải tình trạng tương tự này:

$ git merge-base --all 90d64557 05b3dd8f 
711d1ad9772e42d64e5ecd592bee95fd63590b86 
f303c59666877696feef62844cfbb7960d464fc1 
$ 

Với 2 cơ sở hợp nhất, một 3-way merge là không thể. Do đó, chiến lược 'đệ quy' giải quyết điều này bằng cách recursing đầu tiên vào một hợp nhất của hai cam kết:

$ git merge-base 711d1ad9 f303c596 
3f5db59435ffa4a453e5e82348f478547440e7eb 
$ 

OK, chỉ có một cơ sở hợp nhất, vì vậy 3-way việc sáp nhập có thể bắt đầu. những thay đổi ở hai bên là gì?

$ git diff --stat 3f5db594 711d1ad9 
normalize/coll.py  | 116 ++++++++++++++++++++++++++++++++++++++----------- 
normalize/visitor.py | 49 ++++++++++----------- 
tests/test_property.py | 10 +++-- 
3 files changed, 120 insertions(+), 55 deletions(-) 
$ git diff --stat 3f5db594 f303c596 
normalize/identity.py | 38 +++++++++++++++++++++++++++++++------- 
tests/test_property.py | 2 ++ 
2 files changed, 33 insertions(+), 7 deletions(-) 
$ 

Hai diffs cả đã thay đổi đối với cùng một tập tin, vì vậy họ không thể được giải quyết bằng một chiến lược đơn giản chỉ dùng phiên bản mới hơn của mỗi tập tin từ mỗi bên (một chỉ số merge). Thay vào đó, git lấy tập tin mới từ một phía, và cố gắng áp dụng các miếng vá từ phía bên kia cho nó.Kết quả là một kết hợp cam kết, mà có thể được mô phỏng như thế này:

$ git checkout -b tmp 
Switched to a new branch 'tmp' 
$ git reset --hard f303c59666877696feef62844cfbb7960d464fc1 
HEAD is now at f303c59 record_id: throw a more helpful error if record identity is not hashable 
$ git merge 711d1ad9772e42d64e5ecd592bee95fd63590b86 
Auto-merging tests/test_property.py 
Merge made by the 'recursive' strategy. 
normalize/coll.py  | 116 ++++++++++++++++++++++++++++++++++++++----------- 
normalize/visitor.py | 49 ++++++++++----------- 
tests/test_property.py | 10 +++-- 
3 files changed, 120 insertions(+), 55 deletions(-) 
$ git diff --stat 3f5db594 HEAD tests/test_property.py 
tests/test_property.py | 12 +++++++++--- 
1 file changed, 9 insertions(+), 3 deletions(-) 
$ 

Sau đó nó trở về bản gốc 3-way merge, sử dụng kết quả hợp nhất này là điểm khởi đầu của nó; và điều này cũng liên quan đến các thay đổi đối với cùng một tệp:

$ git diff --stat HEAD 90d64557| grep selector 
normalize/selector.py   | 17 +-- 
tests/test_selector.py   | 19 ++-- 
$ git diff --stat HEAD 05b3dd8f| grep selector 
normalize/selector.py | 29 +++++++++++++++++------------ 
tests/test_selector.py | 9 +++++++++ 
$ 

Tuy nhiên, một lần nữa các thay đổi là các phần khác nhau của tệp và do đó việc sử dụng khác và áp dụng cho phía bên kia thành công. Vì vậy, C git đã có thể giải quyết sự hợp nhất này bằng cách đầu tiên thực hiện hợp nhất 3 chiều trên hai cơ sở hợp nhất của hai điểm bắt đầu, và sau đó thực hiện một phép nối 3 chiều khác trên hai commit ban đầu được sáp nhập và kết quả trung gian của lần hợp nhất đầu tiên.

Độ phân giải tự động của Github không làm điều này. Nó không nhất thiết phải mất khả năng, và tôi không chắc chắn bao nhiêu chiến lược đệ quy nó thực hiện, nhưng nó là sai lầm về mặt thận trọng, đó là chính xác những gì bạn mong đợi một nút màu xanh lá cây lớn như thế để làm :-).

+0

Ngoài ra tốt đẹp về chiến lược hợp nhất đệ quy. +1 Bổ sung tốt cho câu trả lời của riêng tôi. – VonC

5

Không, không phải là khoảng merging. It is about rebasing.

Bạn nên thử và rebase, trong repo địa phương của bạn (nhân bản của your fork), otherbranch trên đầu trang của master.

tiên, đảm bảo tổng thể là một trong những gần đây nhất từ ​​repo thượng nguồn gốc:

fork

cd /your/local/repo 
git remote add upstream /url/original/repo 
git fetch upstream 

# Make sure you don't have any local commmit on your master 
git branch -f master upstream/master # reset your master branch 
            # to the one from upstream repo 
git checkout otherbranch 
git rebase master 

Đó rebase sẽ tạo ra mâu thuẫn, mà bạn nên giải quyết, git add, và sau đó git rebase --continue.

Cuối cùng, chỉ cần push --force chi nhánh của bạn vào ngã ba: sẽ tự động cập nhật yêu cầu kéo của bạn (không cần làm gì khác).

git push -u -f otherbranch origin 

(nếu nó đã đẩy một lần, một mình một git push nên là đủ)

Xem more tips about pull-requests here.

+0

OK, tôi nghĩ điều đó có ý nghĩa. Cảm ơn! – jpimentel

0

Theo mặc định Git không biết liệu nó có thể tự động hợp nhất chi nhánh của bạn hay không trước khi xác nhận thông báo cam kết cho cam kết hợp nhất.

Nếu bạn biết bạn sẽ không có bất kỳ mâu thuẫn, bạn có thể tự động hóa quá trình này của đệ quy tự động kết hợp bằng cách thay đổi GIT_EDITOR để công cụ không tương tác, ví dụ bằng cách thêm cat hoặc true:

GIT_EDITOR=true git merge otherbranch 

Tương tự cho pull. Bạn cũng có thể chỉ định chiến lược hợp nhất như -X theirs hoặc -X ours.

hoặc phương pháp khác là rebase (thêm -r vào lệnh pull).

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