Git Interactive Merge?


78

Tôi có hai nhánh với cùng một tệp (trong trường hợp bạn đang thắc mắc đó là tệp .sql) và tôi muốn hợp nhất nó một cách tương tác.

Tôi muốn mở một chương trình khác giống như khi có xung đột (hoặc dòng lệnh) và chọn chính xác những dòng sẽ đi đến đâu.

Có cách nào để làm điều này không?

Câu trả lời:


84

Có, nhưng nó sẽ chủ yếu bằng cách làm cho điều đó xảy ra theo cách thủ công. Bạn sẽ nói với Git rằng bạn đang hợp nhất hai nhánh có liên quan, nhưng nó không nên cố gắng xác nhận kết quả của riêng nó, (được chỉnh sửa để thêm: cũng như tua đi nhanh nếu nó cho rằng việc hợp nhất là không đáng kể):

git merge --no-commit --no-ff branch-to-merge

Sau đó, bạn sẽ yêu cầu git cho tệp khi nó xuất hiện trong hai nhánh:

git show HEAD:filename >filename.HEAD
git show branch-to-merge:filename >filename.branch

và cơ sở hợp nhất của họ,

git show `git merge-base HEAD branch-to-merge`:filename  >filename.base

Bạn sẽ hợp nhất chúng bằng bất kỳ công cụ nào bạn muốn (ví dụ:)

meld filename.{HEAD,branch,base}

bạn sẽ tạo giai đoạn đó ( git add filename), và sau đó cam kết hợp nhất ( git commit).


2
Tự hỏi điều tương tự Graham ... Tôi đã thử làm git merge --no-commit branchvà nó kết thúc hợp nhất nó ... Điều tôi muốn là kết thúc với 3 tệp hoặc 2 tệp. Đó là tôi có thể sử dụng một khác biệt và di chuyển mọi thứ tôi muốn vào tệp đó.
Steven

Nếu bạn muốn lệnh hợp nhất ban đầu để mọi thứ một mình, được thực hiện theo cách thủ công, bạn có thể gọi nó là git merge -s oursgiữ mọi thứ như ở nhánh hiện tại, nhưng sau đó tùy thuộc vào bạn để đảm bảo rằng các thay đổi trong các tệp khác sẽ kết thúc.
Phil Miller

@Steven; Tôi nghĩ ý tưởng là bạn bỏ qua tệp đã hợp nhất và sử dụng tệp HEAD và tệp nhánh, tức là "hai tệp" bạn đang theo dõi là HEAD: tên tệp và nhánh-to-merge: tên tệp.
Adrian Mouat,

7
Git Gotcha: git merge --no-commit --no-ffsẽ không phạm bất cứ điều gì, hãy xem câu trả lời của @ Brad-O bên dưới. Bạn phải bao gồm--no-ff
Ron Wertlen

1
@Kootoopas: vâng
Phil Miller

41

Cách dễ nhất là làm git merge <other_branchsau đó git mergetoolđể giải quyết xung đột bằng đồ thị. Xem # 10935226 để biết cách thiết lập mergetool.

Vấn đề là, tệp đã thay đổi của bạn có thể hợp nhất nhanh hơn với tệp cũ hơn. Vậy thì bạn phải khéo léo hơn một chút.

Novelocrat cung cấp một cách tuyệt vời để tìm hiểu sâu hơn một chút, nhưng bạn thường sẽ phải thay đổi lệnh ban đầu thành git merge --no-commit --no-ff <other_branch>vì --no-commit thực sự có nghĩa là "Không cam kết hợp nhất ... trừ khi đó là hợp nhất tua đi nhanh." Đó là một chút khó khăn đối với nhiều người đang cố gắng làm chính xác những gì bạn muốn.

Đôi khi, cách ít khó hiểu nhất lại không phong cách lắm: kiểm tra nhánh khác trong một bản sao làm việc khác, sử dụng công cụ hợp nhất yêu thích của bạn để có được phiên bản bạn muốn trong thư mục bạn muốn, sau đó cam kết nó.


13
10935226 là số của câu hỏi này. Ý bạn là gì khi viết ở đó?
Mathieu K.

32

Theo ý chính này, nơi tạm thời có thể là một nhánh hiện có.

https://gist.github.com/katylava/564416


Trên tổng thể:

git checkout -b temp

Tạm thời:

git merge --no-commit --no-ff refactor

… Giai đoạn nào của mọi thứ, vì vậy:

git reset HEAD

Sau đó, bắt đầu thêm các phần bạn muốn:

git add --interactive

1
Điều này đã hoạt động, nhưng tôi phải bỏ 'head' trong 'git reset head', nhưng git reset vẫn hoạt động tốt.
Micah

Trận chung kết git commitkhông hợp nhất! - Làm thế nào để tôi hoàn thành việc hợp nhất cuối cùng?
Robert Siemer

@RobertSiemer Có lẽ tôi đoán bạn có thể thực hiện hợp nhất bình thường trong các bước tiếp theo: git co master; git merge temp
Victor Choy

Phần hay là patchtùy chọn từ git add --interactive, cho phép bạn phân chia các phần của một khác biệt, như được mô tả trong sách git .
djvg

30

Từ chi nhánh bạn muốn hợp nhất thành:

git checkout -p branch_to_merge --

Thao tác này sẽ không kiểm tra branch_to_merge, nhưng sẽ cho phép bạn thêm tương tác các nhóm từ bản vá (khác biệt).

http://git-scm.com/docs/git-checkout


1
Điều này rất dễ sử dụng để hợp nhất tương tác - cảm ơn!
cbcoutinho

Điều này thực hiện chính xác những gì tôi đang tìm kiếm. Tại sao đây không phải là câu trả lời được chấp nhận?
iliis

Lệnh này trình bày từng "phần" (sự khác biệt trong các tệp được nhóm gần nhau) và tùy chọn "có" hoặc "không" để sử dụng nó hay không. Rất hữu dụng.
Mark Lakata

1
Đối với mọi thứ bạn đã thực hiện trên nhánh và không nằm trên nhánh chính, điều này giả định rằng nó sẽ bị xóa. Đó không phải là chiến lược hợp nhất thông minh nhất.
Anne van Rossum

0

Bạn có thể chỉ cần sử dụng WinMerge , DiffMerge hoặc bất kỳ công cụ giao diện người dùng khác / hợp nhất có sẵn nào để thực hiện công việc theo cách thủ công. Nếu bạn muốn nối nó vào "git difftool", bạn có thể tìm kiếm trực tuyến để tìm cách làm cho những công cụ đó hoạt động với git.


0

Cách tốt nhất tôi đã tìm thấy để làm điều này là:

  1. Kiểm tra chi nhánh với các thay đổi của bạn
  2. Tạo một nhánh mới từ thời điểm đó
  3. Đặt lại nhánh mới của bạn về cam kết mà bạn muốn so sánh và xây dựng. Đặt lại sẽ là đặt lại "hỗn hợp" theo mặc định, có nghĩa là nó sẽ không thay đổi "cây làm việc", tức là các tệp mã thực tế
  4. Tại thời điểm này, trình soạn thảo văn bản của tôi (VSCode) cho tôi thấy sự khác biệt giữa các tệp hiện tại của tôi và cam kết mà tôi đặt lại. Tôi có thể chỉnh sửa mã để chọn dòng nào tôi muốn cam kết. Điều này cho phép tôi thấy mọi thứ mà chi nhánh của tôi đã thay đổi và xác nhận mọi dòng mã mà tôi sẽ cam kết. Điều này hữu ích chẳng hạn như trước khi hợp nhất các thay đổi của tôi trở lại sản xuất.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.