2015-05-12 15 views
5

Tôi cần mang theo một số sửa lỗi đã được thực hiện cho chi nhánh develop vào master. Tôi muốn tập tin A giống hệt nhau trong developmaster.Làm thế nào để tôi chọn một phần git cherry mà không hủy hoại hợp nhất trong tương lai?

Thông thường, tôi sẽ git cherry-pick các cam kết có ảnh hưởng đến A, nhưng một số những cam kết cũng ảnh hưởng đến các file BC, nơi B là một tập tin đó tồn tại trong master nhưng tôi không muốn thay đổi nêu ra, và là một C tệp chưa tồn tại trong master.

Khi bản phát hành tiếp theo được thực hiện tại một số thời điểm trong tương lai, develop sẽ được hợp nhất thành master. Nếu tôi git cherry-pick -n các cam kết mà tôi muốn bây giờ, tôi sẽ phải hủy thay đổi đối với B và giải quyết xung đột cho không tồn tại C trước khi cam kết. Khi hợp nhất thực tế từ develop thành master xảy ra, tôi sẽ muốn thay đổi đối với BC, nhưng tôi sẽ không thực sự nhận được chúng, vì tôi đã nhầm lẫn với những thay đổi đó trong cherry-pick, phải không?

Tôi nên làm gì? Nếu tôi git checkout <latest_commit_hash> A, điều đó cũng không gây ra xung đột hợp nhất khó chịu trong tương lai?

+0

Tôi nghĩ rằng bạn có thể tạo 'temp' chi nhánh từ thạc sĩ, cherry-đỉnh cam kết từ 'develop' (hoặc chỉ cần sao chép các tập tin bạn cần), hơn sáp nhập' temp' và' master'. Nhưng tôi không chắc chắn. – gomons

+0

Bạn cũng có thể cân nhắc tạo bản vá mặc dù đó là một kỹ thuật nâng cao hơn. Đây là một hướng dẫn ngắn gọn: http://makandracards.com/makandra/2521-git-how-to-create-and-apply-patches – neontapir

Trả lời

0

Với git-cherry-pick không có cách nào tốt để tránh xung đột hợp nhất sẽ xảy ra với chủ đề với các thay đổi được chọn hợp nhất với chính (nơi thay đổi được chọn).

Tôi khuyên bạn nên thực hiện thao tác chọn cherry, sau đó thực hiện kết hợp thử nghiệm cục bộ và khám phá xem xung đột có phải là thứ mà Git không thể quản lý mà không cần sự can thiệp của người dùng trước khi bạn lo lắng về việc tránh xung đột.

Một trong những thủ đoạn tôi có xu hướng phải làm gì để bắt chước một phần cherry-picks là:

git cherry-pick <commitish> 
git checkout HEAD~ -- <path of unwanted change in file> 
git checkout HEAD~ -- <path of unwanted change in file> 
git checkout HEAD~ -- <path of unwanted change in file> 
git checkout HEAD~ -- <path of unwanted change in file> 
git commit -am "squash me" 
git rebase -i HEAD~~ 

Các squash các cherry-pick và kiểm tra/phục hồi lại với nhau.

2

Nói chung tránh git cherry-pick nếu các chi nhánh đó được hợp nhất bất kỳ lúc nào trong tương lai.

Dường như với tôi rằng git rebase thực sự có thể trợ giúp nếu chi nhánh phát triển là địa phương và không hiển thị công khai. Nếu những người khác đã thấy những thay đổi của bạn và những cam kết đó có cha mẹ khác nhau, bạn không thể tránh hợp nhất.

giả sử bạn có n cam kết sau khi đường chính trong phát triển và bạn có m1, m2, m3 cam kết trong n mà bạn muốn chia sẻ với đường chính.

nếu bạn làm:

git checkout development # go to development branch 
git rebase -i mainline # reorder all commits in development 

bạn sẽ nhận được một cửa sổ soạn thảo cho thấy bạn là một cam kết trên mỗi dòng. nếu bạn đặt các cam kết của m1, m2, m3 lên đầu dòng và chọn edit (thay vì pick) git sẽ sắp xếp lại các cam kết của bạn như bạn đã yêu cầu (đầu commit cũ nhất và dưới cùng mới nhất) và nó sẽ dừng trước mỗi cam kết được đánh dấu là chỉnh sửa.

sau đó bạn có thể làm:

git add file1 
git commit    # commit only file1 
git commit -a   # commit the rest 
git rebase --continue # continue rebasing 

sau đó bạn có thể rebase khác thời gian để di chuyển các cam kết không mong muốn hơn nữa trong lịch sử thay đổi của bạn. nếu bạn hài lòng với nhật ký của mình (nghĩa là: tất cả các commit bạn cần trong mainline là trên đầu các thay đổi trong mainline và không có gì khác; vì vậy bạn có thể hợp nhất nhanh) bạn chọn commit cam kết bạn muốn từ nhánh phát triển của mình (bởi SHA) và hợp nhất.

git checkout mainline 
git log development # assume acf123 is the last commit you want 
git merge acf123  # fast forward to the right commit 

also see:

0

Nếu tôi git checkout phát triển - A, sẽ không phải là cũng gây ra một cuộc xung đột nhập khó chịu trong Tương lai?

Không, không phải bản thân nó sẽ không. Hợp nhất hoạt động bằng cách so sánh từng mẹo với cơ sở hợp nhất và sau đó so sánh hai tập hợp thay đổi. Nếu cả hai nhánh thực hiện các thay đổi tương tự, không có xung đột.

Khác thay đổi, trên một trong hai nhánh, đến hoặc quá gần các đường thay đổi chung trên cả hai nhánh, có thể xuất hiện dưới dạng xung đột. Cách để ngăn chặn những người đó là cho git một cơ sở hợp nhất chính xác bằng cách ghi lại một hợp nhất từ ​​nội dung chung.

# merging master and develop, but there are common changes and 
# also changes that conflict only with those common changes. 
# supply git's merge with the common changes as part of the base, 
# so it will see that it needs to resolve only those other changes 

# check out the current merge base 
git checkout $(git merge-base master develop) 

# make the changes you're merging 
git checkout develop -- file_A 
git commit -m "cherrypicking file_A as of develop @ $(git rev-parse develop)" 

# (for ensuite) 
base=$(git rev-parse HEAD) 

# record that both branches have those changes 
git checkout develop 
git merge -s ours $base -m "recording common content from previous cherry-picks" 

git checkout master 
git merge -s ours $base -m "recording common content from previous cherry-picks" 

# and now this merge will get an accurate base: 
git merge develop 

Bây giờ là: tác dụng duy nhất của những $base sáp nhập là để ghi lại những nội dung phổ biến như tổ tiên để cả hai lời khuyên chi nhánh, cho việc hợp nhất develop-master một căn cứ chính xác từ đó để giải quyết những thay đổi khác.

mới cam kết được lịch sử lại phù hợp với thực tiễn được đưa ra trong một sử dụng rộng rãi successful git branching model.


Nếu, về cách nhóm của bạn diễn giải cam kết, để lại nguồn gốc của nội dung phổ biến đó chỉ được ghi trong văn bản của thư cam kết là thích hợp hơn, git cũng đã được đề cập đến. Thay vì ghi nhận tổ tiên vĩnh viễn, qua kiểm xuất và sáp nhập sau khi chuyển nhượng base trên, bạn cũng

echo $(git rev-parse master master~) $base > .git/info/grafts 
echo $(git rev-parse develop develop~) $base >>.git/info/grafts 
git checkout master 
git merge develop 

# later, whenever you want -- the ancestry above is strictly repo-local 
rm .git/info/grafts 

Tổ tiên có thể được ghi trong .git/info/grafts là repo địa phương. Các lệnh hợp nhất của bạn sẽ thấy nó và kết quả sẽ chính xác. Nhược điểm duy nhất cho điều này là vì các cơ sở không thực sự được ghi lại những người khác sẽ có cùng một rắc rối lặp đi lặp lại nó - rất khó trừ khi bạn đang làm criss-cross merges hoặc cũng cherrypicking đến các chi nhánh khác.

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