Hợp nhất Git mà không có cam kết tự động


402

Có thể làm một git merge, nhưng không có một cam kết?

"Man git merge" nói điều này:

With --no-commit perform the merge but pretend the merge failed and do not autocommit,
to give the user a chance to inspect and further tweak the merge result before
committing.

Nhưng khi tôi cố gắng sử dụng git mergevới --no-commitnó vẫn tự động cam kết. Đây là những gì tôi đã làm:

$> ~/git/testrepo$ git checkout master
Switched to branch 'master'

$> ~/git/testrepo$ git branch
* master
  v1.0

$> ~/git/testrepo$ git merge --no-commit v1.0
Updating c0c9fd2..18fa02c
Fast-forward
 file1 |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

$> ~/git/testrepo$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)

Sau đó git logcho thấy tất cả các cam kết từ nhánh v1.0 được sáp nhập vào chủ.

Câu trả lời:


616

Lưu ý đầu ra trong khi thực hiện hợp nhất - nó đang nói Fast Forward

Trong những tình huống như vậy, bạn muốn làm:

git merge v1.0 --no-commit --no-ff

7
Điều gì xảy ra nếu có một bản án.
Jürgen Paul

20
@PinnutUndertheSea Chuyển tiếp nhanh không bao giờ gây ra xung đột. Trong trường hợp hợp nhất "thực" mà không chuyển tiếp nhanh, --no-commitcông tắc chỉ có hiệu lực nếu không xảy ra xung đột, trong trường hợp xung đột, git sẽ không bao giờ tự động cam kết.
gronostaj

38
FYI: Nếu bạn muốn hợp nhất các thay đổi và sau đó cam kết như thể bạn đã nhập thủ công tất cả các thay đổi bạn đã hợp nhất (trái ngược với hợp nhất truyền thống), bạn cần phải chạy rm .git/MERGE_HEADsau đó, điều này sẽ buộc git quên rằng việc hợp nhất đã xảy ra.
Jonn

7
FYI: Đây là đầu ra mẫu để hợp nhất thành công:Automatic merge went well; stopped before committing as requested
kevinarpe 17/03/2017

6
Rõ ràng git merge BRANCHENAME --no-commit --no-ffđã để lại không gian làm việc của tôi trong trạng thái "NHANH CHÓNG". Không hoàn toàn chắc chắn những gì nó làm chính xác, nhưng một chu kỳ đơn giản git stash savegit stash popdường như đưa mọi thứ trở lại bình thường; chỉ với các tệp được sửa đổi từ nhánh mục tiêu đúng vị trí như dự định và không còn trạng thái KHẨN CẤP.
MoonLite

49

Bạn đang hiểu nhầm ý nghĩa của sự hợp nhất ở đây.

Việc --no-commitngăn chặn CAM KẾT MERGE xảy ra và điều đó chỉ xảy ra khi bạn hợp nhất hai lịch sử chi nhánh khác nhau; trong ví dụ của bạn không phải như vậy vì Git chỉ ra rằng đó là một sự hợp nhất "chuyển tiếp nhanh" và sau đó Git chỉ áp dụng các cam kết đã có trên nhánh một cách tuần tự.


12
Điều đó sẽ không (imo) nhất thiết phải làm sáng tỏ sự nhầm lẫn; Tôi nghĩ rằng đây là một lần (tương đối hiếm) các tài liệu thực sự rõ ràng: git help merge=> "Với việc --no-committhực hiện hợp nhất nhưng giả vờ hợp nhất không thành công và không tự động, để cho người dùng cơ hội kiểm tra và điều chỉnh thêm kết quả hợp nhất trước khi cam kết. " Chìa khóa tất nhiên là sử dụng nó cùng với--no-ff
michael

6
... có lẽ sẽ bớt khó hiểu hơn khi thoát khỏi thuật ngữ nghiêm ngặt và mô tả nó theo cách này: một "git merge" không chuyển tiếp nhanh không có một cam kết hợp nhất vì thực sự không có sự hợp nhất nào cả. Trên thực tế đây là tình huống lý tưởng: chuyển tiếp nhanh là một điều tốt, và không có thêm "cam kết hợp nhất" này làm cho Sense. Đây là hành vi mặc định tốt và không nên bị vô hiệu hóa. (Theo cách nói đúng, chuyển tiếp nhanh là một loại hợp nhất, nhưng nó không phải là "hợp nhất thực sự".)
michael

4
nó liên quan đến các chính sách của dự án, trong một số trường hợp, thật hữu ích khi có / buộc các "cam kết hợp nhất" đó ngay cả khi đó là ff vì bạn cần đánh dấu việc đưa tính năng vào nhánh chính.
Samus_

7
...gì. Được rồi, tôi nghĩ rằng git là khá nhiều không thể thay đổi. Câu trả lời này đặc biệt đã thuyết phục tôi dùng thử Mercurial.
Brian Gordon

24

Nếu bạn chỉ muốn thực hiện tất cả các thay đổi trong một cam kết như thể bạn tự gõ, --squash cũng sẽ làm như vậy

$ git merge --squash v1.0
$ git commit

1
Đây có phải là hiệu ứng tương tự nhưgit merge v1.0 --no-commit --no-ff
jpierson

2
Không, hiệu quả khác nhau. Squash tạo ra một cam kết mới với hàm băm mới. Nó kết hợp tất cả các xác nhận trong một nhánh thành một cam kết cho việc hợp nhất.
Kavi Siegel

23

Tôi thích cách này vì vậy tôi không cần phải nhớ bất kỳ thông số hiếm.

git merge branch_name

Sau đó, nó sẽ nói chi nhánh của bạn đi trước " #" cam kết, bây giờ bạn có thể tắt các cam kết này và đưa chúng vào các thay đổi làm việc với các điều sau:

git reset @~#

Ví dụ: nếu sau khi hợp nhất, nó là 1 cam kết trước, sử dụng:

git reset @~1

Lưu ý: Trên Windows, cần báo giá. (Như Josh đã lưu ý trong các bình luận), vd:

git reset "@~1"

4
Trên cửa sổ, cần trích dẫn:git reset "@~1"
Josh

1

Khi có một cam kết duy nhất trong chi nhánh, tôi thường làm

git merge branch_name --ff
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.