2013-08-07 32 views
87

Tôi có 2 nhánh git branch1 và branch2 và tôi muốn hợp nhất file.py trong branch2 vào tệp.py trong branch1 và chỉ tệp đó.Cách hợp nhất các tệp cụ thể từ các chi nhánh Git

Về bản chất tôi chỉ muốn làm việc trên file.py trong branch1 nhưng muốn tận dụng lệnh kết hợp. Cách tốt nhất để làm việc này là gì?

+0

có thể trùng lặp của [? làm thế nào để bạn ghép các tập tin có chọn lọc với git hợp nhất] (http://stackoverflow.com/questions/449541/how-do-you-merge-selective-files-with- git-merge) –

+0

Bản sao có thể có của [Làm cách nào để hợp nhất các thay đổi vào một tệp duy nhất, thay vì tha n cam kết hợp nhất?] (https://stackoverflow.com/questions/10784523/how-do-i-merge-changes-to-a-single-file-rather-than-merging-commits) – fbmd

Trả lời

99

Câu trả lời được chấp nhận đã đề cập đến sử dụng git checkout. Hiện tại, có thể có nội dung trong file.py từ branch2 không còn có thể áp dụng được trong branch1. Tình huống như vậy sẽ yêu cầu chọn một số thay đổi và để lại những thay đổi khác. Vì vậy, để có toàn quyền kiểm soát thực hiện một hợp nhất tương tác bằng cách sử dụng --patch switch:

$ git checkout --patch branch2 file.py 

Phần chế độ tương tác trong man page của git-add(1) giải thích các phím đó sẽ được sử dụng:

y - stage this hunk 
n - do not stage this hunk 
q - quit; do not stage this hunk nor any of the remaining ones 
a - stage this hunk and all later hunks in the file 
d - do not stage this hunk nor any of the later hunks in the file 
g - select a hunk to go to 
/- search for a hunk matching the given regex 
j - leave this hunk undecided, see next undecided hunk 
J - leave this hunk undecided, see next hunk 
k - leave this hunk undecided, see previous undecided hunk 
K - leave this hunk undecided, see previous hunk 
s - split the current hunk into smaller hunks 
e - manually edit the current hunk 
? - print help 

Việc phân chia lệnh đặc biệt hữu ích.

+1

Đó là một tính năng thú vị – rwolst

+0

Điều này hoạt động hoàn hảo. Cảm ơn bạn đã bao gồm văn bản trợ giúp nhắc lệnh. Sẽ không thể sử dụng nếu không có nó. – James

+1

Làm cách nào chúng tôi có thể sử dụng bản vá và đồng thời sử dụng công cụ hợp nhất? thay vì các công cụ quan trọng – Gabriel

12

Có phải tất cả các sửa đổi đối với file.py trong số branch2 trong cam kết của riêng chúng, tách biệt với các sửa đổi đối với các tệp khác không? Nếu vậy, bạn có thể chỉ đơn giản là cherry-pick những thay đổi trên:

git checkout branch1 
git cherry-pick <commit-with-changes-to-file.py> 

Nếu không, merge không hoạt động trên con đường cá nhân ... bạn cũng có thể chỉ cần tạo một bản vá git diff của file.py thay đổi từ branch2git apply họ branch1:

git checkout branch2 
git diff <base-commit-before-changes-to-file.py> -- file.py > my.patch 
git checkout branch1 
git apply my.patch 
80

Như đã nêu trong phần nhận xét, đây không phải là "hợp nhất", đó là lý do liên kết bên dưới sử dụng dấu ngoặc kép. Tuy nhiên, tôi hiếm khi cần bất cứ điều gì phức tạp như các áp phích khác mô tả, vì vậy tôi nghĩ rằng nó hữu ích, nếu không phải là một giải pháp thích hợp cho câu hỏi của OP.

Kiểm tra trang này: Git Tip: How to "Merge" Specific Files from Another Branch Nó cung cấp cách đơn giản nhất để thực hiện việc này, IMHO.

Về cơ bản, để áp dụng nó vào tình hình của bạn:

$ git checkout branch1 # i.e. make sure you're in branch1 
$ git checkout branch2 file.py 

Peasy dễ dàng, file.py hiện đang ở branch1.

+62

Dễ dàng, nhưng đó không phải là thực sự là một * hợp nhất *. Nó chỉ ghi đè lên 'file.py' với bất kỳ thứ gì trong nhánh 2. –

+3

Vô cùng hữu ích khi bạn muốn chỉ xem một vài tệp từ một tính năng sớm để chuẩn bị. Chúng tôi cần một số tệp từ một chi nhánh tính năng để lập chỉ mục một số dữ liệu trước khi phần còn lại của đối tượng địa lý cố gắng sử dụng dữ liệu được lập chỉ mục. Cảm ơn! –

+0

Nếu bạn hợp nhất lại tệp từ branch1 đến branch2 thì sao? Bạn sẽ nhận được xung đột! – Amir

2

Để chỉ hợp nhất các thay đổi từ chi nhánh file.py của chi nhánh2, hãy thực hiện các thay đổi khác.

git checkout -B wip branch2 
git read-tree branch1 
git checkout branch2 file.py 
git commit -m'merging only file.py history from branch2 into branch1' 
git checkout branch1 
git merge wip 

Hợp nhất sẽ không bao giờ xem xét bất kỳ tệp nào khác. Bạn có thể cần phải '-f' các checkouts nếu cây là đủ khác nhau.

Lưu ý rằng điều này sẽ để branch1 trông như thể mọi thứ trong lịch sử của branch2 đến điểm đó đã được hợp nhất, có thể không phải là điều bạn muốn. Một phiên bản tốt hơn của thanh toán đầu tiên ở trên có lẽ là

git checkout -B wip `git merge-base branch1 branch2` 

trong trường hợp này được thông báo cam kết có lẽ nên cũng được

git commit -m"merging only $(git rev-parse branch2):file.py into branch1" 
5

Không có câu trả lời nào khác hiện tại sẽ thực sự "hợp nhất" các tệp, như thể bạn đang sử dụng lệnh hợp nhất. Nếu bạn thực sự muốn tận dụng lợi thế của việc sáp nhập bằng cách sử dụng thông tin từ một tổ tiên chung, bạn có thể làm theo một thủ tục dựa trên một trong những tìm thấy trong "Advanced Merging" section của Hướng dẫn tham khảo git.

Đối với giao thức này, tôi giả sử bạn muốn hợp nhất tệp 'path/to/file.txt' từ nguồn gốc/chính vào HEAD - sửa đổi khi thích hợp. (Bạn không cần phải có trong thư mục trên cùng của kho lưu trữ của bạn, nhưng nó giúp.)

# Find the merge base SHA1 (the common ancestor) for the two commits: 
git merge-base HEAD origin/master 

# Get the contents of the files at each stage 
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt 
git show HEAD:path/to/file.txt > ./file.ours.txt 
git show origin/master:path/to/file.txt > ./file.theirs.txt 

# You can pre-edit any of the files (e.g. run a formatter on it), if you want. 

# Merge the files 
git merge-file -p ./file.ours.txt ./file.common.txt ./file.theirs.txt > ./file.merged.txt 

# Resolve merge conflicts in ./file.merged.txt 
# Copy the merged version to the destination 
# Clean up the intermediate files 

git merge-file nên sử dụng tất cả các thiết lập mặc định của bạn hợp nhất để định dạng và những thứ tương tự.

Cũng lưu ý rằng nếu bạn "của chúng ta" là phiên bản bản sao làm việc và bạn không muốn trở thành quá thận trọng, bạn có thể hoạt động trực tiếp trên file:

git merge-base HEAD origin/master 
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt 
git show origin/master:path/to/file.txt > ./file.theirs.txt 
git merge-file path/to/file.txt ./file.common.txt ./file.theirs.txt 
2

Bạn có thể stashstash pop file :

git checkout branch1 
git checkout branch2 file.py 
git stash 
git checkout branch1 
git stash pop 
Các vấn đề liên quan