Có một tùy chọn git-merge --dry-run không?


725

Tôi đang hợp nhất trong một chi nhánh xa có thể có nhiều xung đột. Làm thế nào tôi có thể biết nếu nó sẽ có xung đột hay không?

Tôi không thấy bất cứ điều gì như --dry-runtrên git-merge.


5
Vì phân nhánh rẻ với Git, tại sao không kiểm tra một bản sao và sau đó bạn không cần phải chạy khô? Bạn chỉ có thể vứt bản sao sau đó.
Alexander Mills

Câu trả lời:


812

Như đã lưu ý trước đó, vượt qua trong --no-commitcờ, nhưng để tránh cam kết chuyển tiếp nhanh, cũng chuyển qua --no-ff, như vậy:

$ git merge --no-commit --no-ff $BRANCH

Để kiểm tra các thay đổi theo giai đoạn:

$ git diff --cached

Và bạn có thể hoàn tác hợp nhất, ngay cả khi đó là hợp nhất chuyển tiếp nhanh:

$ git merge --abort

51
Điều này là tuyệt vời, nhưng vẫn sẽ sửa đổi bản sao làm việc của bạn. Nếu repo của bạn là một máy chủ web trực tiếp thì bạn có thể đang phục vụ các tệp có xung đột.
dave1010

21
Bạn thực sự không thể thực hiện hợp nhất mà không ảnh hưởng đến bản sao làm việc.
mipadi

55
Đúng, nhưng một cái gì đó như git merge --only-if-there-wont-be-any-conflictshoặc git diff --show-conflicts <commit>sẽ thực sự tiện dụng. Xấu hổ là không thể, hoặc tôi đang thiếu một cái gì đó?
dave1010

344
@ dave1010 Bạn không bao giờ nên xử lý việc hợp nhất trên một máy chủ web trực tiếp !!! Đó là những gì hộp phát triển của bạn dành cho! Sửa lỗi nhánh "prod" và sau đó đẩy nó đến máy chủ web thực.
jpswain

52
Nếu bạn làm việc trên một máy chủ trực tiếp / sản xuất, bạn không bao giờ muốn làm bất cứ điều gì ngoài git pull --ff-only!
ThiefMaster

237

Tôi chỉ phải thực hiện một phương thức tự động tìm thấy xung đột giữa kho lưu trữ và điều khiển từ xa. Giải pháp này thực hiện hợp nhất trong bộ nhớ để nó không chạm vào chỉ mục, cũng như cây làm việc. Tôi nghĩ rằng đây là cách an toàn nhất có thể bạn có thể giải quyết vấn đề này. Đây là cách nó hoạt động:

  1. Tìm nạp từ xa vào kho lưu trữ của bạn. Ví dụ: git fetch origin master
  2. Chạy git merge-base: git merge-base FETCH_HEAD master
  3. Chạy git merge-tree: git merge-tree mergebase master FETCH_HEAD( mergebase là id thập lục phân mà cơ sở hợp nhất được in ở bước trước)

Bây giờ giả sử rằng bạn muốn hợp nhất chủ từ xa với chủ địa phương, nhưng bạn có thể sử dụng bất kỳ nhánh nào. git merge-treesẽ thực hiện hợp nhất trong bộ nhớ và in kết quả ra đầu ra tiêu chuẩn. Grep cho các mẫu <<hoặc >>. Hoặc bạn có thể in đầu ra ra một tệp và kiểm tra xem. Nếu bạn tìm thấy một dòng bắt đầu bằng 'thay đổi trong cả hai' thì rất có thể sẽ có xung đột.


41
Câu trả lời này được đánh giá thấp, IMHO, vì đây là một giải pháp sạch mà không cần chạm vào bản sao hoặc chỉ mục hoạt động.
sschuberth

23
BTW, các bước 2 và 3 có thể được hợp nhất thành một bước, sử dụng toán tử backtick của bảng điều khiển Linux, để đánh giá nội dung của nó:git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
jakub.g

15
Thêm vào [bí danh] trong .gitconfig: Dry = "! F () {git merge-tree` git merge-base $ 2 $ 1` $ 2 $ 1;}; f " chủ dev
Noel

8
Dòng GIT fav mới của tôi: git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"Đơn giản là tuyệt vời! +100
Rudie

4
Trong thử nghiệm này, tôi thấy grepping cho 'thay đổi trong cả hai cờ' hợp nhất trong đó cả hai nhánh sửa đổi cùng một tệp, ngay cả khi chúng không dẫn đến xung đột hợp nhất. Để chỉ xác định các xung đột thực tế, tôi thấy cần phải grep cho đánh dấu xung đột bắt đầu như thế này: +<<<<<<< .ourvì vậy tôi sử dụng một biểu thức grep nhưgrep -q '^+<* \.our$'
Guy

55

Giải pháp vũ phu đơn giản của tôi cho việc này là:

  1. Tạo một nhánh "tiền chính" (từ khóa học chính)

  2. Hợp nhất tất cả những điều bạn muốn vào pre-master này.
    Sau đó, bạn có thể thấy cách hợp nhất đã xảy ra mà không cần chạm vào chủ.

    • Hợp nhất tiền chủ thành chủ HOẶC
    • Hợp nhất tất cả các chi nhánh phát hành Wannabe thành chủ

Dù sao, tôi sẽ làm theo lời khuyên của @ cam80.


5
Tôi thích giải pháp @akostajti, nhưng đây vẫn là một lựa chọn bị đánh giá thấp khác. Trong thực tế, tôi thích phòng thủ và tạo một nhánh tạm thời mới (tất nhiên chỉ khi tôi mong đợi xung đột, nếu không nó sẽ là một sự quá mức), và nếu có gì đó không ổn, chỉ cần xóa nó.
jakub.g

1
dunno nếu đây là một giải pháp "bẩn" hay không, nhưng nó thực sự làm được việc. Tôi thích nó! (Y)
sara

3
Đây phải là giải pháp được chấp nhận, imo. Đó là nhanh chóng, dễ dàng, an toàn, có thể đảo ngược, trực quan và miễn là không có thay đổi nào trước khi bạn bắt đầu, nó sẽ không có tác dụng phụ.
Bob Ray

3
Giải pháp này cho bạn không hiểu cách thức hoạt động của git. Nhánh chỉ là con trỏ và bạn chỉ đang tạo một con trỏ dự phòng. Bạn có một cảm giác tồi tệ rằng bằng cách nào đó bạn có thể làm tổn thương việc sáp nhập chi nhánh của bạn nhưng bạn không thể. Bạn luôn có thể làm git merge --abortnếu có xung đột, git reset --hard HEAD~1nếu có hợp nhất hoặc git reset --hard origin/master. Tạo một nhánh khác mang lại cho bạn cảm giác an toàn nhưng nếu bạn học cách git hoạt động, bạn sẽ hiểu đó là nỗi sợ bị đặt nhầm chỗ. Khi mối quan tâm là về việc không thay đổi bản sao làm việc, điều này không cung cấp giải pháp.
Thibault D.

@ thibault-d Hãy nghĩ về giải pháp phức tạp như thế nào khi bạn không bắt đầu với một nhánh sạch. git merge --no-commitsẽ không hủy bỏ hợp nhất nếu nó có thể được chuyển tiếp nhanh. git merge --abortkhông hoạt động nếu nó được sáp nhập. Nếu bạn muốn viết điều này dưới dạng một tập lệnh, thật khó xử, vì git mergekhông trả lời với các mã lỗi đủ tốt để giải thích các loại xung đột khác nhau. Làm việc với một nhánh mới ngăn không cho tập lệnh bị hỏng rời khỏi repo của bạn ở trạng thái cần can thiệp thủ công. Chắc chắn bạn không thể mất bất cứ thứ gì. Nhưng nó dễ dàng hơn để xây dựng khác.
Erik Aronesty

47

Hoàn tác hợp nhất với git rất dễ dàng, bạn thậm chí không nên lo lắng về việc chạy khô:

$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world

EDIT: Như đã lưu ý trong các bình luận bên dưới, nếu bạn có thay đổi trong thư mục làm việc hoặc khu vực tổ chức, bạn có thể muốn bỏ chúng trước khi thực hiện các thao tác trên (nếu không chúng sẽ biến mất theo cách git resettrên)


7
Đơn giản chỉ cần kiểm tra xem việc hợp nhất sẽ được chuyển tiếp nhanh (FF) hay không là vấn đề kiểm tra danh sách git branch --contains HEADhoặc thậm chí trực tiếp hơn, chỉ cần sử dụnggit merge --ff-only
Brian Phillips

7
git reset --hard là một trong số ít các lệnh xóa thông tin không có backout mà git có, vì vậy cần hết sức thận trọng. Như vậy, -1
Kzqai

8
@Tchalvak vẫn còn reflog.
Kissaki

3
--dry-runsẽ không "đơn giản kiểm tra nếu hợp nhất sẽ được chuyển tiếp nhanh". Nó sẽ trả về đầu ra chính xác mà một sự hợp nhất sẽ: các tập tin, xung đột, vv Liệu điều đó có thực sự thú vị không?
Rudie

3
làm thế nào về git stash; git reset --hard? @BrianPhillips
Whisperer Code

41

Tôi đã tạo một bí danh để làm điều này và làm việc như một cơ duyên, tôi làm điều này:

 git config --global alias.mergetest '!f(){ git merge --no-commit --no-ff "$1"; git merge --abort; echo "Merge aborted"; };f '

Bây giờ tôi chỉ cần gọi

git mergetest <branchname>

Để tìm hiểu nếu có bất kỳ xung đột.


Xuất sắc! Tôi đang giữ cái này
qbert65536

28

Chỉ cần khác nhánh hiện tại của bạn so với nhánh từ xa, điều này sẽ cho bạn biết điều gì sẽ thay đổi khi bạn thực hiện thao tác kéo / hợp nhất.

#see diff between current master and remote branch
git diff master origin/master

1
Ý tưởng thú vị. Làm thế nào tôi sẽ nhìn vào đầu ra đó và xác định xem hợp nhất sẽ hoạt động hay không?
MatrixFrog

6
Điều này sẽ không cho bạn biết nếu có bất kỳ xung đột nào xảy ra ... nhưng nó sẽ cho bạn ý tưởng chung về những gì sẽ xảy ra nếu bạn thực hiện thao tác kéo / hợp nhất.
timh

10
Điều này sẽ chỉ cho bạn biết sự khác biệt giữa hai nhánh, nó sẽ không cho bạn biết kết quả của sự hợp nhất sẽ là gì. Đây là một sự khác biệt quan trọng vì việc sáp nhập trong một số trường hợp sẽ tự động thực hiện các thay đổi từ các chi nhánh khác nhau tùy thuộc vào thời điểm chúng được cam kết. Vì vậy, về bản chất, thực hiện một khác biệt có thể khiến bạn nghĩ rằng một số thay đổi của bạn sẽ được hoàn nguyên khi trong thực tế, quá trình hợp nhất sẽ tự động thực hiện các thay đổi mới hơn so với những thay đổi cũ hơn. Hy vọng rằng có ý nghĩa.
markquezada

3
Để xây dựng dựa trên nhận xét của @ mirthlab, sẽ có một sự khác biệt đáng kể giữa diff và merge nếu trước đó ai đó đã thực hiện hợp nhất với chiến lược hợp nhất "của chúng ta" (hoặc một số bản sửa lỗi hợp nhất thủ công khác); khác biệt cũng sẽ cho bạn thấy sự khác biệt đã được tính là "hợp nhất".
Tao

21

Tôi sử dụng lệnh git request-pull để làm như vậy. Nó cho phép bạn xem mọi thay đổi sẽ xảy ra khi hợp nhất, nhưng không làm gì trên kho lưu trữ cục bộ hoặc từ xa .

Ví dụ, hãy tưởng tượng bạn muốn hợp nhất một nhánh có tên "Feature-x" vào nhánh chính của bạn

git request-pull master origin feature-x

sẽ cho bạn thấy một bản tóm tắt về những gì sẽ xảy ra (mà không làm gì cả):

The following changes since commit fc01dde318:
    Layout updates (2015-06-25 11:00:47 +0200)
are available in the git repository at:
    http://fakeurl.com/myrepo.git/ feature-x
for you to fetch changes up to 841d3b41ad:
----------------------------------------------------------------
john (2):
    Adding some layout
    Refactoring
ioserver.js            |   8 +++---
package.json           |   7 +++++-
server.js              |   4 +--
layout/ldkdsd.js       | 277 +++++++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+), 7 deletions(-)
create mode 100644 layout/ldkdsd.js

Nếu bạn thêm -ptham số, bạn cũng sẽ nhận được văn bản vá đầy đủ, chính xác như nếu bạn đang thực hiện một git diff trên mỗi tệp đã thay đổi.


3
Bạn có thể làm cho điều này rõ ràng hơn một chút bằng cách thêm những gì masteroriginlàm trong các tùy chọn dòng lệnh, và nếu tôi là một người địa phương branch1và muốn thực hiện một request-pullnhánh tính năng cục bộ branch2thì sao? Tôi vẫn cần originchứ? Tất nhiên, người ta luôn có thể đọc tài liệu.
Ela782

Đáng buồn là lệnh này chỉ hoạt động nếu Rev # 2 là tên nhánh, nó không hoạt động cho băm: /
Jared Grubb

20

Tôi ngạc nhiên không ai đề nghị sử dụng các bản vá lỗi.

Giả sử bạn muốn thử nghiệm một hợp nhất từ your_branchvào master(tôi giả sử bạn đã masterkiểm tra ra):

$ git diff master your_branch > your_branch.patch
$ git apply --check your_branch.patch
$ rm your_branch.patch

Điều đó sẽ làm các trick.

Nếu bạn gặp lỗi như

error: patch failed: test.txt:1
error: test.txt: patch does not apply

điều đó có nghĩa là bản vá không thành công và việc hợp nhất sẽ tạo ra xung đột. Không có đầu ra có nghĩa là bản vá sạch và bạn có thể dễ dàng hợp nhất chi nhánh


Lưu ý rằng điều này sẽ không thực sự thay đổi cây làm việc của bạn (tất nhiên ngoài việc tạo tệp vá lỗi, nhưng bạn có thể xóa nó một cách an toàn sau đó). Từ tài liệu áp dụng git:

--check
    Instead of applying the patch, see if the patch is applicable to the
    current working tree and/or the index file and detects errors. Turns
    off "apply".

Lưu ý cho bất kỳ ai thông minh hơn / có kinh nghiệm với git hơn tôi: vui lòng cho tôi biết nếu tôi sai ở đây và phương pháp này hiển thị hành vi khác với hợp nhất thông thường. Có vẻ lạ là trong hơn 8 năm qua, câu hỏi này đã tồn tại, không ai có thể đề xuất giải pháp dường như rõ ràng này.


Phương pháp này là câu trả lời được chấp nhận cho câu hỏi này và có một số lưu ý trong các nhận xét như "git không thể sử dụng chiến lược hợp nhất 'đệ quy' và" tệp vá lỗi gây ra lỗi cho các tệp mới ". Nếu không, có vẻ tuyệt vời.
neno

1
Một cách ngắn hơn mà không tạo một tệp vá tạm thời : git diff master your_branch | git apply --check.
ks1322

9

Điều này có thể thú vị: Từ tài liệu:

Nếu bạn đã thử hợp nhất dẫn đến xung đột phức tạp và muốn bắt đầu lại, bạn có thể khôi phục bằng git merge --abort .

Nhưng bạn cũng có thể làm theo cách ngây thơ (nhưng chậm):

rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)

(Lưu ý: Nó sẽ không hoạt động khi chỉ nhân bản vào / tmp, bạn cần một bản sao để đảm bảo rằng các thay đổi không được cam kết sẽ không xung đột).


2
Nếu tất cả những gì bạn cần là một cái búa ... :) +1
kaiser

Bản sao sạch có thể thu được với cp -r repository/.git /tmp/repository/.git, cd /tmp/repository, git reset --hard, git add --all, git reset --hard(đối với biện pháp tốt), git status(để kiểm tra xem nó sạch).
ADTC

8

Tôi biết rằng đây là một câu hỏi cũ, nhưng đây là câu hỏi đầu tiên xuất hiện trên tìm kiếm của Google.

Git giới thiệu một tùy chọn --ff-only khi hợp nhất.

Từ: http://git-scm.com/docs/git-merge


- chỉ

Từ chối hợp nhất và thoát với trạng thái khác không trừ khi CHÍNH hiện tại đã được cập nhật hoặc hợp nhất có thể được giải quyết dưới dạng chuyển tiếp nhanh.

Làm điều này sẽ cố gắng hợp nhất và chuyển tiếp nhanh, và nếu nó không thể hủy bỏ và nhắc nhở bạn rằng không thể thực hiện chuyển tiếp nhanh, nhưng khiến cho nhánh làm việc của bạn không bị ảnh hưởng. Nếu nó có thể chuyển tiếp nhanh, thì nó sẽ thực hiện hợp nhất trên nhánh làm việc của bạn. Tùy chọn này cũng có sẵn trên git pull. Vì vậy, bạn có thể làm như sau:

git pull --ff-only origin branchA #See if you can pull down and merge branchA

git merge --ff-only branchA branchB #See if you can merge branchA into branchB

1
Điều đó sẽ thực hiện hợp nhất nếu nó có thể được thực hiện với chuyển tiếp nhanh, đó không phải là điều tôi muốn trong câu hỏi ban đầu. Tôi nghĩ rằng câu trả lời được chấp nhận có nửa kia sửa nó.
Otto

Thực sự, git ưa thích nhắc nhở làm giảm nhu cầu tôi có cho loại điều này.
Otto

2
Nó không thực sự giống nhau. Thoát khỏi trạng thái khác không vì hợp nhất không thể được giải quyết vì chuyển tiếp nhanh không có nghĩa là có xung đột . Nó chỉ có nghĩa là lịch sử đã chuyển hướng và một cam kết hợp nhất là cần thiết.
ADTC

7

Tôi sử dụng git log để xem những gì đã thay đổi trên nhánh tính năng từ nhánh chính

git log does_this_branch..contain_this_branch_changes

ví dụ: để xem những gì cam kết trong một nhánh tính năng chưa / được hợp nhất thành chủ:

git log master..feature_branch

3

Nếu bạn muốn chuyển nhanh từ B sang A, thì bạn phải chắc chắn rằng git log B..A không cho bạn thấy gì, tức là A không có gì mà B không có. Nhưng ngay cả khi B..A có thứ gì đó, bạn vẫn có thể hợp nhất mà không có xung đột, vì vậy, ở trên cho thấy hai điều: sẽ có một chuyển tiếp nhanh, và do đó bạn sẽ không bị xung đột.


2

Giải pháp của tôi là hợp nhất ngược.

Thay vì hợp nhất chi nhánh của bạn vào chi nhánh "mục tiêu" từ xa, hãy hợp nhất chi nhánh đó vào chi nhánh của bạn.

git checkout my-branch
git merge origin/target-branch

Bạn sẽ thấy nếu có bất kỳ xung đột và có thể lên kế hoạch về cách giải quyết chúng.

Sau đó, bạn có thể hủy bỏ hợp nhất qua git merge --aborthoặc (nếu không có bất kỳ xung đột và hợp nhất nào xảy ra) quay lại cam kết trước đó thông quagit reset --hard HEAD~1


-2

Tạo một bản sao tạm thời của bản sao làm việc của bạn, sau đó hợp nhất vào đó và tìm khác biệ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.