Cách hợp nhất các tệp cụ thể từ các nhánh Git


179

Tôi có 2 nhánh git Branch1 và Branch2 và tôi muốn hợp nhất file.txt trong nhánh2 thành file.py trong nhánh1 và chỉ có tệp đó.

Về bản chất, tôi chỉ muốn làm việc với file.txt trong nhánh1 nhưng muốn tận dụng lệnh hợp nhất. Cách tốt nhất để làm việc này là gì?



Câu trả lời:


207

Khi nội dung là file.pytừ branch2 rằng không còn được áp dụng cho branch1 , nó đòi hỏi chọn một số thay đổi và để lại những người khác. Để kiểm soát hoàn toàn, hãy hợp nhất tương tác bằng cách sử dụng công --patchtắc:

$ git checkout --patch branch2 file.py

Phần chế độ tương tác trong trang man để 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

Lệnh split đặc biệt hữu ích.


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

@Gabriel Tôi đã sử dụng Git ngay cả với các tệp vá và tarball vì rất dễ tạo repo ( git init <dir>) và cuối cùng ném nó đi ( rm -r <dir>).
pdp

105

Mặc dù không phải là hợp nhất mỗi lần, đôi khi toàn bộ nội dung của tệp khác trên nhánh khác là cần thiết. Bài đăng trên blog của Jason Rudolph cung cấp một cách đơn giản để sao chép các tệp từ nhánh này sang nhánh khác. Áp dụng kỹ thuật như sau:

$ git checkout branch1 # ensure in branch1 is checked out and active
$ git checkout branch2 file.py

Bây giờ file.pylà trong chi nhánh1 .


91
Dễ dàng, nhưng đó không thực sự là một sự hợp nhất . Nó chỉ ghi đè lên file.pybất cứ thứ gì trong nhánh 2.
Greg Hewgill

Điều gì nếu bạn hợp nhất lại tập tin từ nhánh 1 sang nhánh2? Bạn sẽ có xung đột!
Amir

Điều này có giữ lại lịch sử cam kết?
C2H50H

18

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

Đố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ừ origin / master thành HEAD - sửa đổi cho phù hợp. (Bạn không cần phải nằm trong thư mục trên cùng của kho lưu trữ, 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 cài đặt hợp nhất mặc định của bạn để định dạng và tương tự.

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

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

15

Có phải tất cả các sửa đổi file.pytrong branch2cam kết của riêng họ, tách biệt với sửa đổi cho các tệp khác? Nếu vậy, bạn có thể chỉ cần cherry-pickthay đổi:

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

Mặt khác, mergekhông hoạt động trên các đường dẫn riêng lẻ ... bạn cũng có thể tạo ra một git diffbản vá các file.pythay đổi từ branch2git applychúng thành branch1:

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

8

Bạn có thể stashstash poptập tin:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop

Điều này ghi đè lên nhánh1 / file.py bằng nội dung của nhánh2 / file.py thay vì hợp nhất sẽ tạo ra xung đột hợp nhất để giải quyết.
plumSemPy

2

Để chỉ hợp nhất các thay đổi từ chi nhánh 2 file.py, 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 thậm chí sẽ không bao giờ nhìn vào bất kỳ tập tin khác. Bạn có thể cần '-f' kiểm tra nếu cây đủ khác nhau.

Lưu ý rằng điều này sẽ khiến nhánh1 trông như thể mọi thứ trong lịch sử của nhánh2 đến thời đ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 đó, thông điệp cam kết có lẽ cũng nên

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

0

Tôi cũng ở trong tình huống tương tự, tôi muốn hợp nhất một tệp từ một nhánh có nhiều cam kết trên đó trên 2 nhánh. Tôi đã thử nhiều cách ở trên và những cách khác tôi tìm thấy trên internet và tất cả đều thất bại (vì lịch sử cam kết rất phức tạp) vì vậy tôi quyết định làm theo cách của mình (cách điên rồ).

git merge <other-branch>
cp file-to-merge file-to-merge.example
git reset --hard HEAD (or HEAD^1 if no conflicts happen)
cp file-to-merge.example file-to-merge

0

Những gì tôi đã làm là một chút thủ công, nhưng tôi:

  1. Sáp nhập các nhánh bình thường; Hoàn nguyên hợp nhất vớirevert ;
  2. Kiểm tra tất cả các tập tin của tôi để HEAD~1 , nghĩa là, trạng thái của chúng trong cam kết hợp nhất;
  3. Đã khởi động lại các cam kết của tôi để che giấu tin tặc này khỏi lịch sử cam kết.

Xấu xí? Đúng. Dễ nhớ? Cũng có.

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.