Làm cách nào để giải quyết xung đột hợp nhất trong Git?
git
cài đặt mặc định . Quản lý để đạt trang bắt đầu SE cho tôi ngày hôm nay, 2017, với 1,3 triệu lượt xem và hàng ngàn phiếu bầu cả hai chiều. Hấp dẫn.
Làm cách nào để giải quyết xung đột hợp nhất trong Git?
git
cài đặt mặc định . Quản lý để đạt trang bắt đầu SE cho tôi ngày hôm nay, 2017, với 1,3 triệu lượt xem và hàng ngàn phiếu bầu cả hai chiều. Hấp dẫn.
Câu trả lời:
Thử: git mergetool
Nó mở một GUI giúp bạn vượt qua từng xung đột và bạn có thể chọn cách hợp nhất. Đôi khi nó đòi hỏi một chút chỉnh sửa tay sau đó, nhưng thường thì nó là đủ. Nó tốt hơn nhiều so với việc làm toàn bộ bằng tay chắc chắn.
Theo nhận xét @JoshGlover:
Lệnh
không nhất thiết phải mở GUI trừ khi bạn cài đặt. Chạy
git mergetool
cho tôi kết quảvimdiff
là được sử dụng. Bạn có thể cài đặt một trong các công cụ sau đây để sử dụng nó thay vì:meld
,opendiff
,kdiff3
,tkdiff
,xxdiff
,tortoisemerge
,gvimdiff
,diffuse
,ecmerge
,p4merge
,araxis
,vimdiff
,emerge
.
Dưới đây là quy trình mẫu để sử dụng vimdiff
để giải quyết xung đột hợp nhất. Dựa trên liên kết này
Bước 1 : Chạy các lệnh sau trong thiết bị đầu cuối của bạn
git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false
Điều này sẽ đặt vimdiff làm công cụ hợp nhất mặc định.
Bước 2 : Chạy lệnh sau trong terminal
git mergetool
Bước 3 : Bạn sẽ thấy màn hình vimdiff ở định dạng sau
╔═══════╦══════╦════════╗
║ ║ ║ ║
║ LOCAL ║ BASE ║ REMOTE ║
║ ║ ║ ║
╠═══════╩══════╩════════╣
║ ║
║ MERGED ║
║ ║
╚═══════════════════════╝
4 quan điểm này là
ĐỊA PHƯƠNG - đây là tập tin từ chi nhánh hiện tại
BASE - tổ tiên chung, cách tệp nhìn trước cả hai thay đổi
XÓA - tập tin bạn đang hợp nhất vào chi nhánh của bạn
SỨC MẠNH - kết quả hợp nhất, đây là những gì được lưu trong repo
Bạn có thể điều hướng trong số các chế độ xem này bằng ctrl+ w. Bạn có thể trực tiếp đạt đến chế độ xem MERGED bằng cách sử dụng ctrl+ wtheo sau j.
Thông tin thêm về điều hướng vimdiff ở đây và ở đây
Bước 4 . Bạn có thể chỉnh sửa chế độ xem NHIỀU theo cách sau
Nếu bạn muốn nhận được các thay đổi từ XÓA
:diffg RE
Nếu bạn muốn nhận thay đổi từ BASE
:diffg BA
Nếu bạn muốn nhận thay đổi từ ĐỊA PHƯƠNG
:diffg LO
Bước 5 . Lưu, thoát, cam kết và dọn dẹp
:wqa
lưu và thoát khỏi vi
git commit -m "message"
git clean
Xóa các tệp bổ sung (ví dụ * .orig) được tạo bởi công cụ diff.
git mergetool -y
để lưu một vài tổ hợp phím nếu bạn hợp nhất nhiều tệp cùng một lúc.
git mergetool
cho tôi kết quả vimdiff
là được sử dụng. Bạn có thể cài đặt một trong những công cụ sau để sử dụng thay thế : meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge
.
git mergetool -t bc3
).
Đây là trường hợp sử dụng có thể xảy ra, từ đầu:
Bạn sẽ có một số thay đổi, nhưng rất tiếc, bạn không cập nhật:
git fetch origin
git pull origin master
From ssh://gitosis@example.com:22/projectname
* branch master -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.
Vì vậy, bạn cập nhật và thử lại, nhưng có một xung đột:
git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master
From ssh://gitosis@example.com:22/projectname
* branch master -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.
Vì vậy, bạn quyết định xem xét các thay đổi:
git mergetool
Ôi trời ơi, ngược dòng đã thay đổi một số thứ, nhưng chỉ để sử dụng những thay đổi của tôi ... không ... những thay đổi của họ ...
git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"
Và sau đó chúng tôi thử một lần cuối cùng
git pull origin master
From ssh://gitosis@example.com:22/projectname
* branch master -> FETCH_HEAD
Already up-to-date.
Ta-da!
git merge --help
this question
Tôi thấy các công cụ hợp nhất hiếm khi giúp tôi hiểu được xung đột hoặc giải quyết. Tôi thường thành công hơn khi xem các dấu xung đột trong trình soạn thảo văn bản và sử dụng nhật ký git làm phần bổ sung.
Dưới đây là một vài lời khuyên:
Điều tốt nhất tôi đã tìm thấy là sử dụng kiểu xung đột hợp nhất "diff3":
git config merge.conflictstyle diff3
Điều này tạo ra các dấu hiệu xung đột như thế này:
<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a
feature/topic branch.
>>>>>>>
Phần giữa là những gì tổ tiên chung trông giống như. Điều này rất hữu ích vì bạn có thể so sánh nó với các phiên bản trên cùng và dưới cùng để hiểu rõ hơn về những gì đã thay đổi trên mỗi nhánh, điều này cho bạn ý tưởng tốt hơn về mục đích của mỗi thay đổi là gì.
Nếu xung đột chỉ là một vài dòng, điều này thường làm cho xung đột rất rõ ràng. (Biết cách khắc phục xung đột rất khác nhau; bạn cần lưu ý về những gì người khác đang làm. Nếu bạn bối rối, có lẽ tốt nhất là gọi người đó vào phòng của bạn để họ có thể thấy bạn đang nhìn gì tại.)
Nếu xung đột kéo dài hơn, thì tôi sẽ cắt và dán từng phần trong ba phần thành ba tệp riêng biệt, chẳng hạn như "của tôi", "chung" và "của họ".
Sau đó, tôi có thể chạy các lệnh sau để xem hai khối khác nhau gây ra xung đột:
diff common mine
diff common theirs
Điều này không giống như sử dụng một công cụ hợp nhất, vì một công cụ hợp nhất sẽ bao gồm tất cả các khối khác nhau không xung đột. Tôi thấy rằng để được phân tâm.
Ai đó đã đề cập đến vấn đề này, nhưng hiểu được ý định đằng sau mỗi hunk diff thường rất hữu ích để hiểu được xung đột đến từ đâu và cách xử lý nó.
git log --merge -p <name of file>
Điều này cho thấy tất cả các cam kết đã chạm vào tệp đó ở giữa tổ tiên chung và hai đầu bạn đang hợp nhất. (Vì vậy, nó không bao gồm các cam kết đã tồn tại trong cả hai nhánh trước khi hợp nhất.) Điều này giúp bạn bỏ qua các khối khác biệt rõ ràng không phải là một yếu tố trong xung đột hiện tại của bạn.
Xác nhận thay đổi của bạn với các công cụ tự động.
Nếu bạn có các bài kiểm tra tự động, hãy chạy chúng. Nếu bạn có một lint , chạy nó. Nếu đó là một dự án có thể xây dựng, thì hãy xây dựng nó trước khi bạn cam kết, v.v. Trong mọi trường hợp, bạn cần thực hiện một chút thử nghiệm để đảm bảo các thay đổi của bạn không phá vỡ bất cứ điều gì. (Heck, ngay cả một sự hợp nhất mà không có xung đột có thể phá vỡ mã làm việc.)
Lên kế hoạch trước; giao tiếp với đồng nghiệp.
Lập kế hoạch trước và nhận thức được những gì người khác đang làm việc có thể giúp ngăn ngừa xung đột hợp nhất và / hoặc giúp giải quyết chúng sớm hơn - trong khi các chi tiết vẫn còn mới mẻ.
Ví dụ: nếu bạn biết rằng bạn và một người khác đều đang thực hiện các phép tái cấu trúc khác nhau, cả hai sẽ ảnh hưởng đến cùng một tập tin, bạn nên nói chuyện với nhau trước và hiểu rõ hơn về loại thay đổi của mỗi bạn chế tạo. Bạn có thể tiết kiệm đáng kể thời gian và công sức nếu bạn tiến hành thay đổi theo kế hoạch một cách thanh thản hơn là song song.
Đối với các phép tái cấu trúc chính cắt ngang một dải mã lớn, bạn nên cân nhắc việc làm việc một cách nghiêm túc: mọi người ngừng làm việc trên khu vực đó của mã trong khi một người thực hiện tái cấu trúc hoàn chỉnh.
Nếu bạn không thể làm việc bình thường (do áp lực thời gian, có thể), thì việc truyền đạt về xung đột hợp nhất dự kiến ít nhất sẽ giúp bạn giải quyết vấn đề sớm hơn trong khi các chi tiết vẫn còn mới mẻ. Ví dụ: nếu đồng nghiệp đang thực hiện một loạt các cam kết đột phá trong khoảng thời gian một tuần, bạn có thể chọn hợp nhất / rebase trên chi nhánh đồng nghiệp đó một hoặc hai lần mỗi ngày trong tuần đó. Bằng cách đó, nếu bạn tìm thấy xung đột hợp nhất / rebase, bạn có thể giải quyết chúng nhanh hơn nếu bạn chờ vài tuần để hợp nhất mọi thứ lại với nhau trong một lần lớn.
Nếu bạn không chắc chắn về việc hợp nhất, đừng ép buộc.
Sáp nhập có thể cảm thấy quá sức, đặc biệt là khi có rất nhiều tệp xung đột và các dấu xung đột bao gồm hàng trăm dòng. Thông thường, khi ước tính các dự án phần mềm, chúng tôi không bao gồm đủ thời gian cho các mục trên cao như xử lý hợp nhất sởn gai ốc, do đó, cảm giác giống như một lực cản thực sự để dành vài giờ để mổ xẻ mỗi xung đột.
Về lâu dài, lập kế hoạch trước và nhận thức được những gì người khác đang làm là những công cụ tốt nhất để dự đoán xung đột hợp nhất và chuẩn bị cho mình để giải quyết chúng một cách chính xác trong thời gian ngắn hơn.
p4merge
, có thể được cài đặt và sử dụng riêng biệt với các công cụ khác của Perforce (mà tôi chưa sử dụng, nhưng nghe thấy khiếu nại về).
git config merge.conflictstyle diff3
- cảm ơn ngài. Điều này thật tuyệt vời và đã giải phóng tôi khỏi việc cố gắng tìm (và trả $$) cho GUI hợp nhất 3 chiều. IMO điều này tốt hơn bởi vì nó hiển thị tổ tiên chung cũng như cục bộ / từ xa và hiển thị các dòng nhật ký cam kết cuối cùng mà (AFAIK) không có GUI nào thực hiện. Các cam kết chắc chắn giúp bạn xác định mã nào thuộc về nhánh nào.
Xác định các tệp đang xung đột (Git sẽ cho bạn biết điều này).
Mở từng tệp và kiểm tra các khác biệt; Git phân định chúng. Hy vọng nó sẽ rõ ràng phiên bản của mỗi khối để giữ. Bạn có thể cần thảo luận với các nhà phát triển đồng nghiệp đã cam kết mã.
Khi bạn đã giải quyết xung đột trong một tệp git add the_file
.
Khi bạn đã giải quyết tất cả các xung đột, hãy thực hiện git rebase --continue
hoặc bất kỳ lệnh nào mà Git đã nói sẽ làm khi bạn hoàn thành.
git add
giai đoạn tập tin trong chỉ mục; nó không thêm bất cứ thứ gì vào kho lưu trữ. git commit
thêm những thứ vào kho lưu trữ. Việc sử dụng này có ý nghĩa đối với việc hợp nhất - việc hợp nhất sẽ tự động thực hiện tất cả các thay đổi có thể được hợp nhất tự động; bạn có trách nhiệm hợp nhất phần còn lại của các thay đổi và thêm những thay đổi đó vào chỉ mục khi bạn hoàn thành.
Kiểm tra các câu trả lời trong câu hỏi Stack Overflow Hủy bỏ hợp nhất trong Git , đặc biệt là câu trả lời của Charles Bailey trong đó cho thấy cách xem các phiên bản khác nhau của tệp có vấn đề, ví dụ:
# Common base version of the file.
git show :1:some_file.cpp
# 'Ours' version of the file.
git show :2:some_file.cpp
# 'Theirs' version of the file.
git show :3:some_file.cpp
Hợp nhất xung đột xảy ra khi thay đổi được thực hiện cho một tệp cùng một lúc. Đây là cách giải quyết nó.
git
CLIDưới đây là các bước đơn giản phải làm gì khi bạn rơi vào trạng thái xung đột:
git status
(trong Unmerged paths
phần).Giải quyết các xung đột riêng cho từng tệp bằng một trong các cách tiếp cận sau:
Sử dụng GUI để giải quyết các xung đột: git mergetool
(cách dễ nhất).
Để chấp nhận từ xa / phiên bản khác, sử dụng : git checkout --theirs path/file
. Điều này sẽ từ chối mọi thay đổi cục bộ bạn đã làm cho tệp đó.
Để chấp nhận phiên bản cục bộ / của chúng tôi, hãy sử dụng: git checkout --ours path/file
Tuy nhiên, bạn phải cẩn thận, vì những thay đổi từ xa mà xung đột đã được thực hiện vì một số lý do.
Liên quan: Ý nghĩa chính xác của "chúng ta" và "của họ" trong git là gì?
Chỉnh sửa các tệp bị xung đột theo cách thủ công và tìm khối mã giữa <<<<<
/ >>>>>
sau đó chọn phiên bản từ bên trên hoặc bên dưới =====
. Xem: Làm thế nào xung đột được trình bày .
Xung đột đường dẫn và tên tệp có thể được giải quyết bằng git add
/ git rm
.
Cuối cùng, xem lại các tệp đã sẵn sàng để cam kết sử dụng : git status
.
Nếu bạn vẫn còn bất kỳ tệp nào bên dưới Unmerged paths
và bạn đã giải quyết xung đột theo cách thủ công, thì hãy cho Git biết rằng bạn đã giải quyết nó bằng cách : git add path/file
.
Nếu tất cả các xung đột đã được giải quyết thành công, hãy thực hiện các thay đổi bằng cách: git commit -a
và đẩy sang điều khiển từ xa như bình thường.
Xem thêm: Giải quyết xung đột hợp nhất từ dòng lệnh tại GitHub
Để có hướng dẫn thực tế, hãy kiểm tra: Kịch bản 5 - Khắc phục xung đột hợp nhất của Katacoda .
Tôi đã sử dụng thành công DiffMerge có thể so sánh và hợp nhất các tệp trên Windows, macOS và Linux / Unix một cách trực quan.
Nó đồ họa có thể hiển thị các thay đổi giữa 3 tệp và cho phép tự động hợp nhất (khi an toàn để làm như vậy) và toàn quyền kiểm soát chỉnh sửa tệp kết quả.
Nguồn hình ảnh: DiffMerge (ảnh chụp màn hình Linux)
Đơn giản chỉ cần tải xuống và chạy trong repo như:
git mergetool -t diffmerge .
Trên macOS, bạn có thể cài đặt qua:
brew install caskroom/cask/brew-cask
brew cask install diffmerge
Và có lẽ (nếu không được cung cấp), bạn cần trình bao bọc đơn giản bổ sung sau được đặt trong PATH của bạn (ví dụ /usr/bin
):
#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"
Sau đó, bạn có thể sử dụng các phím tắt sau:
Ngoài ra, bạn có thể sử dụng opendiff (một phần của Công cụ Xcode) cho phép bạn hợp nhất hai tệp hoặc thư mục lại với nhau để tạo tệp hoặc thư mục thứ ba.
Nếu bạn đang thực hiện các cam kết nhỏ thường xuyên, thì hãy bắt đầu bằng cách xem các nhận xét cam kết với git log --merge
. Sau đó git diff
sẽ cho bạn thấy những xung đột.
Đối với các xung đột liên quan đến nhiều hơn một vài dòng, sẽ dễ dàng hơn để xem những gì đang diễn ra trong một công cụ GUI bên ngoài. Tôi thích opendiff - Git cũng hỗ trợ vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff, xuất hiện trong hộp và bạn có thể cài git config merge.tool "your.tool"
đặt các công cụ khác: sẽ đặt công cụ đã chọn của bạn và sau đó git mergetool
kết hợp thất bại sẽ hiển thị cho bạn các khác biệt trong bối cảnh.
Mỗi lần bạn chỉnh sửa một tệp để giải quyết xung đột, git add filename
sẽ cập nhật chỉ mục và diff của bạn sẽ không hiển thị nữa. Khi tất cả các xung đột được xử lý và các tệp của chúng đã được xử lý git add
, git commit
sẽ hoàn tất việc hợp nhất của bạn.
Xem cách Xung đột được trình bày hoặc, trong Git, git merge
tài liệu để hiểu các dấu hiệu xung đột hợp nhất là gì.
Ngoài ra, phần Cách giải quyết xung đột giải thích cách giải quyết xung đột:
Sau khi thấy một cuộc xung đột, bạn có thể làm hai điều:
Quyết định không hợp nhất. Việc dọn dẹp duy nhất bạn cần là đặt lại tệp chỉ mục thành
HEAD
cam kết để đảo ngược 2. và dọn sạch các thay đổi của cây làm việc được thực hiện bởi 2. và 3.;git merge --abort
có thể được sử dụng cho việc này.Giải quyết các xung đột. Git sẽ đánh dấu các xung đột trong cây làm việc. Chỉnh sửa các tập tin thành hình và
git add
chúng vào chỉ mục. Sử dụnggit commit
để niêm phong thỏa thuận.Bạn có thể làm việc thông qua xung đột với một số công cụ:
Sử dụng một mergetool.
git mergetool
để khởi chạy một công cụ hợp nhất đồ họa sẽ giúp bạn hoàn thành việc hợp nhất.Nhìn vào khác biệt.
git diff
sẽ hiển thị một diff ba chiều, làm nổi bật những thay đổi từ cảHEAD
vàMERGE_HEAD
các phiên bản.Nhìn vào sự khác biệt từ mỗi chi nhánh.
git log --merge -p <path>
sẽ hiển thị khác trước choHEAD
phiên bản và sau đó làMERGE_HEAD
phiên bản.Nhìn vào bản gốc.
git show :1:filename
hiển thị tổ tiên chung,git show :2:filename
hiển thịHEAD
phiên bản vàgit show :3:filename
hiển thịMERGE_HEAD
phiên bản.
Bạn cũng có thể đọc về các dấu xung đột hợp nhất và cách giải quyết chúng trong phần sách Pro Git Xung đột hợp nhất cơ bản .
Tôi muốn phiên bản của tôi hoặc của họ đầy đủ hoặc muốn xem xét các thay đổi riêng lẻ và quyết định cho từng thay đổi.
Chấp nhận hoàn toàn phiên bản của tôi hoặc của họ :
Chấp nhận phiên bản của tôi (địa phương, của chúng tôi):
git checkout --ours -- <filename>
git add <filename> # Marks conflict as resolved
git commit -m "merged bla bla" # An "empty" commit
Chấp nhận phiên bản của họ (từ xa, của họ):
git checkout --theirs -- <filename>
git add <filename>
git commit -m "merged bla bla"
Nếu bạn muốn làm cho tất cả các tệp xung đột chạy:
git merge --strategy-option ours
hoặc là
git merge --strategy-option theirs
Xem lại tất cả các thay đổi và chấp nhận chúng riêng lẻ
git mergetool
git add <filename>
git commit -m "merged bla bla"
Mặc định mergetool
hoạt động trong dòng lệnh . Làm thế nào để sử dụng một sáp nhập dòng lệnh nên là một câu hỏi riêng biệt.
Bạn cũng có thể cài đặt công cụ trực quan cho việc này, ví dụ meld
và chạy
git mergetool -t meld
Nó sẽ mở phiên bản cục bộ (của chúng tôi), phiên bản "cơ sở" hoặc "hợp nhất" (kết quả hiện tại của việc hợp nhất) và phiên bản từ xa (của họ). Lưu phiên bản đã hợp nhất khi bạn kết thúc, chạy git mergetool -t meld
lại cho đến khi bạn nhận được "Không cần tập tin hợp nhất", sau đó chuyển đến Bước 3. và 4.
Đối với người dùng Emacs muốn giải quyết xung đột hợp nhất một cách thủ công:
git diff --name-status --diff-filter=U
hiển thị tất cả các tệp yêu cầu giải quyết xung đột.
Mở từng tệp một, hoặc tất cả cùng một lúc bằng cách:
emacs $(git diff --name-only --diff-filter=U)
Khi truy cập bộ đệm yêu cầu chỉnh sửa trong Emacs, hãy nhập
ALT+x vc-resolve-conflicts
Điều này sẽ mở ba bộ đệm (của tôi, của họ và bộ đệm đầu ra). Điều hướng bằng cách nhấn 'n' (khu vực tiếp theo), 'p' (khu vực thịnh hành). Nhấn 'a' và 'b' để sao chép vùng của tôi hoặc vùng của chúng vào bộ đệm đầu ra, tương ứng. Và / hoặc chỉnh sửa bộ đệm đầu ra trực tiếp.
Khi kết thúc: Nhấn 'q'. Emacs hỏi bạn nếu bạn muốn lưu bộ đệm này: có. Sau khi hoàn thành đánh dấu bộ đệm, nó được giải quyết bằng cách chạy từ teriminal:
git add FILENAME
Khi kết thúc với tất cả các loại bộ đệm
git commit
để kết thúc hợp nhất.
Khi nói về pull / fetch / merge trong các câu trả lời trên, tôi muốn chia sẻ một mẹo thú vị và hiệu quả,
git pull --rebase
Lệnh trên là lệnh hữu ích nhất trong cuộc sống git của tôi giúp tiết kiệm rất nhiều thời gian.
Trước khi đẩy sự thay đổi mới cam kết của bạn đến máy chủ từ xa, hãy thử git pull --rebase
thay git pull
và bằng tay merge
và nó sẽ tự động đồng bộ hóa mới nhất thay đổi máy chủ từ xa (với lấy + merge) và sẽ đưa địa phương cam kết mới nhất ở trên cùng trong git log. Không cần phải lo lắng về việc kéo / hợp nhất thủ công.
Trong trường hợp có xung đột, chỉ cần sử dụng
git mergetool
git add conflict_file
git rebase --continue
Tìm thông tin chi tiết tại: http://gitolite.com/git-pull--rebase
Đơn giản, nếu bạn biết rõ rằng những thay đổi trong một trong các kho lưu trữ là không quan trọng và muốn giải quyết tất cả các thay đổi có lợi cho cái khác, hãy sử dụng:
git checkout . --ours
để giải quyết các thay đổi có lợi cho kho lưu trữ của bạn , hoặc
git checkout . --theirs
để giải quyết các thay đổi có lợi cho kho khác hoặc kho lưu trữ chính .
Hoặc nếu không, bạn sẽ phải sử dụng công cụ hợp nhất GUI để lần lượt từng tệp một, giả sử công cụ hợp nhất là p4merge
hoặc viết bất kỳ tên nào bạn đã cài đặt
git mergetool -t p4merge
và sau khi hoàn thành một tệp, bạn sẽ phải lưu và đóng, vì vậy tệp tiếp theo sẽ mở.
Vui lòng làm theo các bước sau để khắc phục xung đột hợp nhất trong Git:
Kiểm tra trạng thái Git: trạng thái git
Nhận bản vá : git fetch (kiểm tra bản vá đúng từ cam kết Git của bạn)
Kiểm tra một chi nhánh địa phương (temp1 trong ví dụ của tôi ở đây): git checkout -b temp1
Kéo các nội dung gần đây từ master: git pull --rebase origin master
Bắt đầu mergetool và kiểm tra các xung đột và khắc phục chúng ... và kiểm tra các thay đổi trong nhánh từ xa với nhánh hiện tại của bạn: git mergetool
Kiểm tra lại trạng thái: trạng thái git
Xóa các tệp không mong muốn được tạo cục bộ bởi mergetool, thông thường mergetool tạo tệp bổ sung có phần mở rộng * .orig. Vui lòng xóa tệp đó vì đó chỉ là bản sao và sửa các thay đổi cục bộ và thêm phiên bản chính xác của tệp của bạn. git thêm #your_changed_c chính_files
Kiểm tra lại trạng thái: trạng thái git
Cam kết các thay đổi đối với cùng một id xác nhận (điều này tránh một bộ bản vá riêng biệt mới): git commit --amend
Đẩy đến nhánh chính: git đẩy (vào kho Git của bạn)
Có 3 bước:
Tìm tập tin nào gây ra xung đột bằng lệnh
git status
Kiểm tra các tệp, trong đó bạn sẽ tìm thấy các xung đột được đánh dấu như
<<<<<<<<head
blablabla
Thay đổi nó theo cách bạn muốn, sau đó cam kết bằng các lệnh
git add solved_conflicts_files
git commit -m 'merge msg'
Bạn có thể sửa các xung đột hợp nhất theo một số cách như những cách khác đã nêu chi tiết.
Tôi nghĩ rằng chìa khóa thực sự là biết cách thay đổi chảy với các kho lưu trữ cục bộ và từ xa. Chìa khóa cho việc này là sự hiểu biết theo dõi các chi nhánh. Tôi đã thấy rằng tôi nghĩ về nhánh theo dõi là "phần bị thiếu ở giữa" giữa thư mục tệp thực tế, cục bộ của tôi và từ xa được xác định là gốc.
Cá nhân tôi đã có thói quen 2 điều để giúp tránh điều này.
Thay vì:
git add .
git commit -m"some msg"
Trong đó có hai nhược điểm -
a) Tất cả các tệp mới / thay đổi được thêm vào và có thể bao gồm một số thay đổi không mong muốn.
b) Bạn không được xem lại danh sách tập tin trước.
Vì vậy, thay vì tôi làm:
git add file,file2,file3...
git commit # Then type the files in the editor and save-quit.
Bằng cách này, bạn sẽ cân nhắc nhiều hơn về những tập tin nào được thêm vào và bạn cũng có thể xem lại danh sách và suy nghĩ thêm một chút trong khi sử dụng trình chỉnh sửa cho tin nhắn. Tôi thấy nó cũng cải thiện các thông điệp cam kết của tôi khi tôi sử dụng trình chỉnh sửa toàn màn hình thay vì -m
tùy chọn.
[Cập nhật - khi thời gian trôi qua tôi đã chuyển nhiều hơn sang:
git status # Make sure I know whats going on
git add .
git commit # Then use the editor
]
Ngoài ra (và phù hợp hơn với tình huống của bạn), tôi cố gắng tránh:
git pull
hoặc là
git pull origin master.
bởi vì pull ngụ ý hợp nhất và nếu bạn có các thay đổi cục bộ mà bạn không muốn hợp nhất, bạn có thể dễ dàng kết thúc với mã được hợp nhất và / hoặc xung đột hợp nhất cho mã không nên được hợp nhất.
Thay vào đó tôi cố gắng làm
git checkout master
git fetch
git rebase --hard origin/master # or whatever branch I want.
Bạn cũng có thể thấy điều này hữu ích:
chi nhánh git, ngã ba, tìm nạp, hợp nhất, rebase và clone, sự khác biệt là gì?
git checkout master
và git fetch
và git rebase --hard origin/master
git add .
, liệu nó có lưu các sửa đổi cục bộ của chúng tôi để chúng tôi có thể theo dõi git checkout master
không? hoặc là hai kịch bản khác nhau?
$ git rebase --hard origin/master b5a30cc159ba8dd error: unknown option
hard 'cách sử dụng: git rebase [-i] [tùy chọn] [--exec <cmd>] [--onto <newbase>] [<ngược dòng>] [<chi nhánh>] hoặc: git rebase [-i] [ tùy chọn] [--exec <cmd>] [--onto <newbase>] --root [<chi nhánh>] hoặc: git rebase --continue | - --skip | --edit-todo `
Câu trả lời của CoolAJ86 tổng hợp khá nhiều thứ. Trong trường hợp bạn có các thay đổi trong cả hai nhánh trong cùng một đoạn mã, bạn sẽ phải thực hiện hợp nhất thủ công. Mở tệp trong xung đột trong bất kỳ trình soạn thảo văn bản nào và bạn sẽ thấy cấu trúc sau.
(Code not in Conflict)
>>>>>>>>>>>
(first alternative for conflict starts here)
Multiple code lines here
===========
(second alternative for conflict starts here)
Multiple code lines here too
<<<<<<<<<<<
(Code not in conflict here)
Chọn một trong các lựa chọn thay thế hoặc kết hợp cả hai theo cách bạn muốn mã mới, trong khi loại bỏ các dấu bằng và dấu ngoặc góc bằng nhau.
git commit -a -m "commit message"
git push origin master
git log --merge -p [[--] path]
Dường như không phải lúc nào cũng làm việc cho tôi và thường kết thúc hiển thị mọi cam kết khác nhau giữa hai nhánh, điều này xảy ra ngay cả khi sử dụng --
để tách đường dẫn khỏi lệnh.
Những gì tôi làm để giải quyết vấn đề này là mở ra hai dòng lệnh và trong một lần chạy
git log ..$MERGED_IN_BRANCH --pretty=full -p [path]
và trong cái khác
git log $MERGED_IN_BRANCH.. --pretty=full -p [path]
Thay thế $MERGED_IN_BRANCH
bằng nhánh tôi đã hợp nhất và [path]
với tệp bị xung đột. Lệnh này sẽ ghi lại tất cả các xác nhận, ở dạng bản vá, giữa ( ..
) hai lần xác nhận. Nếu bạn để trống một bên như trong các lệnh trên, git sẽ tự động sử dụng HEAD
(nhánh bạn đang hợp nhất trong trường hợp này).
Điều này sẽ cho phép bạn xem những gì cam kết đã đi vào tệp trong hai nhánh sau khi chúng chuyển hướng. Nó thường làm cho nó dễ dàng hơn nhiều để giải quyết xung đột.
patience
Tôi ngạc nhiên không ai khác nói về việc giải quyết xung đột bằng patience
chiến lược đệ quy hợp nhất. Đối với một cuộc xung đột hợp nhất lớn, sử dụng patience
cung cấp kết quả tốt cho tôi. Ý tưởng là nó sẽ cố gắng khớp các khối chứ không phải các dòng riêng lẻ.
Ví dụ, nếu bạn thay đổi thụt lề của chương trình, chiến lược hợp nhất Git mặc định đôi khi khớp với các dấu ngoặc đơn {
thuộc các chức năng khác nhau. Điều này được tránh với patience
:
git merge -s recursive -X patience other-branch
Từ tài liệu:
With this option, merge-recursive spends a little extra time to avoid
mismerges that sometimes occur due to unimportant matching lines
(e.g., braces from distinct functions). Use this when the branches to
be merged have diverged wildly.
Nếu bạn có xung đột hợp nhất và muốn xem những gì người khác nghĩ đến khi sửa đổi chi nhánh của họ, đôi khi việc so sánh trực tiếp chi nhánh của họ với tổ tiên chung (thay vì chi nhánh của chúng tôi) sẽ dễ dàng hơn. Cho rằng bạn có thể sử dụng merge-base
:
git diff $(git merge-base <our-branch> <their-branch>) <their-branch>
Thông thường, bạn chỉ muốn xem các thay đổi cho một tệp cụ thể:
git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>
Kể từ ngày 12 tháng 12 năm 2016, bạn có thể hợp nhất các chi nhánh và giải quyết xung đột trên github.com
Do đó, nếu bạn không muốn sử dụng dòng lệnh hoặc bất kỳ công cụ của bên thứ 3 nào được cung cấp ở đây từ các câu trả lời cũ hơn , hãy sử dụng công cụ gốc của GitHub.
Bài đăng trên blog này giải thích chi tiết, nhưng điều cơ bản là khi 'hợp nhất' hai chi nhánh thông qua giao diện người dùng, giờ đây bạn sẽ thấy tùy chọn 'giải quyết xung đột' sẽ đưa bạn đến một trình soạn thảo cho phép bạn xử lý các xung đột hợp nhất này.
Nếu bạn muốn hợp nhất từ nhánh (kiểm tra) thành chủ, bạn có thể làm theo các bước sau:
Bước 1 : Đi đến chi nhánh
git checkout test
Bước 2 :
git pull --rebase origin master
Bước 3 : Nếu có một số xung đột, hãy đến các tệp này để sửa đổi nó.
Bước 4 : Thêm những thay đổi này
git add #your_changes_files
Bước 5 :
git rebase --continue
Bước 6 : Nếu vẫn còn xung đột, quay lại bước 3 một lần nữa. Nếu không có xung đột, hãy làm như sau:
git push origin +test
Bước 7 : Và sau đó không có xung đột giữa kiểm tra và chủ. Bạn có thể sử dụng hợp nhất trực tiếp.
Tôi luôn làm theo các bước dưới đây để tránh xung đột.
Bây giờ bạn có thể làm tương tự và duy trì bao nhiêu chi nhánh địa phương bạn muốn và làm việc đồng thời tôi chỉ cần thực hiện kiểm tra git cho chi nhánh của bạn khi cần thiết.
Hợp nhất xung đột có thể xảy ra trong các tình huống khác nhau:
Bạn cần cài đặt một công cụ hợp nhất tương thích với Git để giải quyết các xung đột. Cá nhân tôi sử dụng KDiff3 và tôi thấy nó rất hay và tiện dụng. Bạn có thể tải xuống phiên bản Windows của nó tại đây:
https://sourceforge.net/projects/kdiff3/files/
BTW nếu bạn cài đặt Tiện ích mở rộng Git, có một tùy chọn trong trình hướng dẫn thiết lập để cài đặt Kdiff3.
Sau đó thiết lập cấu hình git để sử dụng Kdiff làm mergetool của nó:
$ git config --global --add merge.tool kdiff3
$ git config --global --add mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add mergetool.kdiff3.trustExitCode false
$ git config --global --add diff.guitool kdiff3
$ git config --global --add difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add difftool.kdiff3.trustExitCode false
(Hãy nhớ thay thế đường dẫn bằng đường dẫn thực tế của tệp exe Kdiff.)
Sau đó, mỗi khi bạn gặp một xung đột hợp nhất, bạn chỉ cần chạy lệnh này:
$git mergetool
Sau đó, nó sẽ mở Kdiff3 và đầu tiên cố gắng tự động giải quyết xung đột hợp nhất. Hầu hết các xung đột sẽ được giải quyết một cách tự nhiên và bạn cần khắc phục phần còn lại bằng tay.
Đây là những gì Kdiff3 trông giống như:
Sau đó, khi bạn đã hoàn tất, hãy lưu tệp và nó chuyển sang tệp tiếp theo có xung đột và bạn làm lại điều tương tự cho đến khi tất cả các xung đột được giải quyết.
Để kiểm tra xem mọi thứ có được hợp nhất thành công hay không, chỉ cần chạy lại lệnh mergetool, bạn sẽ nhận được kết quả này:
$git mergetool
No files need merging
Câu trả lời này là để thêm một giải pháp thay thế cho những người dùng VIM như tôi thích làm mọi thứ trong trình chỉnh sửa.
Tpope đã đưa ra plugin tuyệt vời này cho VIM được gọi là fugitive . Sau khi cài đặt, bạn có thể chạy :Gstatus
để kiểm tra các tệp có xung đột và :Gdiff
để mở Git theo cách hợp nhất 3 cách.
Khi đã hợp nhất 3 cách, fugitive sẽ cho phép bạn nhận được các thay đổi của bất kỳ nhánh nào bạn đang hợp nhất theo cách sau:
:diffget //2
, nhận các thay đổi từ nhánh ban đầu ( HEAD )::diffget //3
, nhận các thay đổi từ việc sáp nhập chi nhánh: Khi bạn đã hoàn tất việc hợp nhất tệp, hãy nhập :Gwrite
vào bộ đệm đã hợp nhất. Vimcasts đã phát hành một video tuyệt vời giải thích chi tiết các bước này.
git fetch
git kiểm tra chi nhánh của bạn
git rebase master
Trong bước này, bạn sẽ cố gắng khắc phục xung đột bằng IDE ưa thích của mình
Bạn có thể theo liên kết này để kiểm tra ho để khắc phục xung đột trong tệp
https://help.github.com/articles/resolve-a-merge-conflict-USE-the-command-line/
git add
git rebase --continue
git commit --amend
git push origin HEAD: refs / dự thảo / master (đẩy như bản nháp)
Bây giờ mọi thứ đều ổn và bạn sẽ tìm thấy cam kết của mình trong gerrit
Tôi hy vọng rằng điều này sẽ giúp mọi người liên quan đến vấn đề này.
Hãy thử Visual Studio Code để chỉnh sửa nếu bạn chưa có. Những gì nó làm là sau khi bạn thử hợp nhất (và tìm ra xung đột hợp nhất) .VS mã tự động phát hiện các xung đột hợp nhất.
Nó có thể giúp bạn rất tốt bằng cách hiển thị những thay đổi được thực hiện cho bản gốc và bạn nên chấp nhận incoming
hoặc
current change
(có nghĩa là bản gốc trước khi hợp nhất) '?.
Nó giúp tôi và nó cũng có thể làm việc cho bạn!
PS: Nó sẽ chỉ hoạt động nếu bạn đã cấu hình git với mã của bạn và Visual Studio Code.
Một cách an toàn hơn để giải quyết xung đột là sử dụng git-mediated (các giải pháp phổ biến được đề xuất ở đây là khá dễ bị lỗi imho).
Xem bài đăng này để giới thiệu nhanh về cách sử dụng nó.
Dành cho những ai đang sử dụng Visual Studio (2015 trong trường hợp của tôi)
Đóng dự án của bạn trong VS. Đặc biệt trong các dự án lớn, VS có xu hướng kỳ dị khi hợp nhất sử dụng UI.
Thực hiện hợp nhất trong dấu nhắc lệnh.
kiểm tra git target_branch
hợp nhất git source_branch
Sau đó mở dự án trong VS và đi đến Team Explorer -> Branch. Bây giờ có một thông báo cho biết Hợp nhất đang chờ xử lý và các tệp xung đột được liệt kê ngay bên dưới tin nhắn.
Nhấp vào tệp xung đột và bạn sẽ có tùy chọn Hợp nhất, So sánh, Lấy nguồn, Lấy mục tiêu. Công cụ hợp nhất trong VS rất dễ sử dụng.
Nếu bạn đang sử dụng intelliJ làm IDE Hãy thử hợp nhất cha mẹ với chi nhánh của bạn bằng cách
git checkout <localbranch>
git merge origin/<remotebranch>
Nó sẽ hiển thị tất cả các xung đột như thế này
A_MBPro: test anu $ git merge origin / Auto-merge src / test / java / com /.../ TestClass.java CONFLICT (nội dung): Hợp nhất xung đột trong src / test / java / com /.../ TestClass.java
Bây giờ lưu ý rằng tệp TestClass.java được hiển thị màu đỏ trong intelliJ Ngoài ra trạng thái git sẽ hiển thị
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: src/test/java/com/.../TestClass.java
Mở tệp trong intelliJ, nó sẽ có các phần với
<<<<<<< HEAD
public void testMethod() {
}
=======
public void testMethod() { ...
}
>>>>>>> origin/<remotebranch>
trong đó CHÍNH là thay đổi trên nhánh cục bộ của bạn và nguồn gốc / là thay đổi từ nhánh từ xa. Ở đây giữ những thứ bạn cần và loại bỏ những thứ bạn không cần. Sau đó, các bước thông thường nên làm. Đó là
git add TestClass.java
git commit -m "commit message"
git push