Sử dụng Git, hiển thị tất cả các xác nhận trong một nhánh, nhưng không hiển thị (các) cam kết khác


465

Tôi có một chi nhánh cũ, mà tôi muốn xóa. Tuy nhiên, trước khi làm như vậy, tôi muốn kiểm tra xem tất cả các cam kết được thực hiện cho chi nhánh này tại một số điểm đã được sáp nhập vào một số chi nhánh khác. Vì vậy, tôi muốn thấy tất cả các cam kết được thực hiện cho chi nhánh hiện tại của tôi chưa được áp dụng cho bất kỳ chi nhánh nào khác [hoặc, nếu điều này là không thể nếu không có kịch bản, làm thế nào để thấy tất cả các cam kết trong một chi nhánh chưa được áp dụng đến một chi nhánh khác?].


Để liệt kê các cam kết bị thiếu giữa hai chi nhánh, bạn có thể sử dụng so sánh-branches.py bitbucket.org/aakef/compare-git-branches
Bernd Schubert

Câu trả lời:


321

Bạn có thể chỉ muốn

git branch --contains branch-to-delete

Điều này sẽ liệt kê tất cả các nhánh có chứa các xác nhận từ "nhánh cần xóa". Nếu nó báo cáo nhiều hơn chỉ là "chi nhánh cần xóa", chi nhánh đã được hợp nhất.

Các lựa chọn thay thế của bạn thực sự chỉ là liệt kê lại những thứ cú pháp. ví dụ git log one-branch..another-branchcho thấy mọi thứ one-branchcần phải có mọi thứ đều another-branchcó.

Bạn cũng có thể quan tâm git show-branchnhư một cách để xem những gì ở đâu.



1
Điểm mấu 'Nếu nó báo cáo một cái gì đó, chi nhánh đã sáp nhập' có thể bị hiểu sai: nếu git branch --contains some-branchchỉ trả lại some-branch, sau đó nó trở lại một cái gì đó, nhưng nó đã không được sáp nhập.
Nhầm lẫn

5
Lưu ý rằng git log foo..barsẽ hiển thị các cam kết giữa mới nhất của thanh và mới nhất của foo, nhưng không phải là các cam kết khác bị mất từ ​​thời gian trở lại. Để xem mọi thứ trong thanh nhưng không phải trong foo, bạn nên sử dụng giải pháp của @ jimmyorr.
Paul A Jungwirth

556

Để xem danh sách các cam kết nằm trên một nhánh nhưng không phải là một nhánh khác, hãy sử dụng git log:

git log --no-merges oldbranch ^newbranch

... đó là, hiển thị nhật ký cam kết cho tất cả các cam kết trên oldbranch không phải trên newbranch. Bạn có thể liệt kê nhiều chi nhánh để bao gồm và loại trừ, ví dụ:

git log  --no-merges oldbranch1 oldbranch2 ^newbranch1 ^newbranch2

Lưu ý: trên Windows ^là một phím thoát, vì vậy nó cần được thoát bằng một phím khác ^:

git log --no-merges oldbranch ^^newbranch

2
Tôi tìm thấy nó tìm kiếm cam kết so sánh git của hai chi nhánh.
Người dùng

25
Điều này thật đúng với gì mà tôi đã tìm kiếm. Nhưng, sử dụng ^như một tiền tố ở đây làm tôi bối rối. Trong bối cảnh này, nó có nghĩa là loại trừ chi nhánh đó. Sử dụng ^như một hậu tố sẽ là một tham chiếu tương đối đến cam kết cha của nhánh đó.
Joe Flynn

4
rất hữu ích cảm ơn. Tôi tò mò, tại sao cờ --no-sáp nhập lại cần thiết? Chắc chắn ai cũng muốn xem những cam kết đó chứ?
Max MacLeod

2
Có muốn sử dụng gitk với điều này? Chỉ cần sử dụng gitk oldbranch ^newbranch --no-merges(Đã thử nghiệm với git 1.8.1.1). Lưu ý bên cạnh, đối với tôi ^có nghĩa là cam kết bao gồm chi nhánh newbranch.
Matt

2
@NazariiGudzovatyi - vâng, có: "-cherry-pick". Có một số lượng lớn các tùy chọn để đăng nhập trên trang tài liệu
romeara

91

Để hiển thị các cam kết trong oldbranch nhưng không hiển thị trong newbranch:

git log newbranch..oldbranch

Để hiển thị khác biệt bởi các cam kết này (lưu ý có ba dấu chấm):

git diff newbranch...oldbranch

Đây là tài liệu có sơ đồ minh họa https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#Commit-Ranges


Xem bình luận của Paul A Jungwirth ở trên. Có vẻ như điều này sẽ bỏ lỡ một số cam kết cũ?
Biến khốn khổ

2
Tôi không chắc những gì cũ cam kết. Về cơ bản, các dấu chấm kép yêu cầu Git giải quyết một loạt các cam kết có thể truy cập được từ một cam kết nhưng không thể truy cập được từ một cam kết khác. Dưới đây là tài liệu với hình minh họa digram git-scm.com/book/en/v2/ Kẻ
Xuân

1
và nếu chúng ta ở hai newbranchhay oldbranch, chúng ta có thể làm git log ..oldbranchhoặc git log newbranch..tương ứng
YakovL

giải pháp jimmyorr của không làm việc cho tôi, nhưng điều này đã nhờ vào hai chấm ..giữa tên của refs. Tôi cũng đã sử dụng --cherry-picktùy chọn để ẩn các xác nhận có mặt trên cả hai nhánh nhưng có hàm băm khác nhau vì chúng được chọn từ cành này sang nhánh khác.
flawyte

58

Đối với những người vẫn đang tìm kiếm một câu trả lời đơn giản, hãy kiểm tra git cherry . Nó so sánh các khác biệt thực tế thay vì băm cam kết. Điều đó có nghĩa là nó chứa các cam kết đã được chọn hoặc nổi loạn.

Đầu tiên kiểm tra chi nhánh bạn muốn xóa:

git checkout [branch-to-delete]

sau đó sử dụng git cherry để so sánh nó với nhánh phát triển chính của bạn:

git cherry -v master

Ví dụ đầu ra:

+ 8a14709d08c99c36e907e47f9c4dacebeff46ecb Commit message
+ b30ccc3fb38d3d64c5fef079a761c7e0a5c7da81 Another commit message
- 85867e38712de930864c5edb7856342e1358b2a0 Yet another message

Lưu ý: -vCờ là bao gồm thông điệp cam kết cùng với hàm băm SHA.

Các dòng có '+' ở phía trước nằm trong nhánh cần xóa, nhưng không phải là nhánh chính. Những người có dấu '-' ở phía trước có một cam kết tương đương trong tổng thể.

Đối với JUST các cam kết không nằm trong tổng thể, kết hợp cherry chọn với grep:

git cherry -v master | grep "^\+"

Ví dụ đầu ra:

+ 8a14709d08c99c36e907e47f9c4dacebeff46ecb Commit message
+ b30ccc3fb38d3d64c5fef079a761c7e0a5c7da81 Another commit message

Tôi đã thử điều này, nhưng nó vẫn báo cáo rằng có nhiều cam kết trong fb (nhánh tính năng) không có trong mb (nhánh chính). Tuy nhiên, nếu tôi ở trong fb và làm một git diff mb, tôi không thấy sự khác biệt. Tôi đã sử dụng rebase và bị đè nén tất cả mọi thứ. Tôi gần như chắc chắn đây là lý do tại sao, nhưng tôi chỉ muốn chắc chắn. Nếu đây là trường hợp, thì tôi sẽ tránh bị đè bẹp nếu có thể; Tôi đang ở trong "trại thông tin không bị mất." Tôi tự hỏi nếu có thể thêm một chế độ hiển thị nhật ký có thể hiển thị hợp nhất như thể chúng là các cuộc nổi loạn để giữ cho lịch sử sạch sẽ và không mất thông tin.
Outis Von Nemo

1
Không chắc chắn về kịch bản chính xác của bạn ở đây, nhưng nếu bạn đã kết hợp nhiều cam kết thành một và so sánh nó với một nhánh khác nơi các cam kết riêng biệt, điều này chắc chắn sẽ không hoạt động. Trong trường hợp đó, bạn có thể chỉ muốn sử dụng difftiện ích unix để so sánh các tệp khác nhau. Hoặc, bạn có thể tạo một nhánh tạm thời và nén tất cả các cam kết tương tự như những gì bạn đã làm với nhánh ban đầu, và sau đó sử dụng cái này, cái mà tôi nghĩ sẽ hiệu quả.
Tim S

50

Trong khi một số câu trả lời được đăng ở đây sẽ giúp tìm thấy những gì bạn tìm kiếm, lệnh phụ sau của nhánh git là một giải pháp phù hợp hơn cho nhiệm vụ của bạn.

--merged được sử dụng để tìm tất cả các nhánh có thể bị xóa một cách an toàn, vì các nhánh đó được chứa đầy đủ bởi HEAD.

Trong khi trong mastermột người có thể chạy lệnh để liệt kê các nhánh, người ta có thể loại bỏ một cách an toàn, như vậy:

git branch --merged
  develop
  fpg_download_links
* master
  master_merge_static

# Delete local and remote tracking branches you don't want
git branch -d fpg_download_links
git push origin :fpg_download_links
git branch -d master_merge_static
git push origin :master_merge_static

# There is also a flag to specify remote branches in the output
git branch --remotes --merged

16

câu trả lời jimmyorr của không hoạt động trên Windows. Nó giúp sử dụng --notthay vì ^như vậy:

git log oldbranch --not newbranch --no-merges

4
Đó là chính xác, +1. Lưu ý rằng mặc dù ^được hỗ trợ trên Windows, nhưng cần phải thoát, trong Windows, là (cái khác) ^: git log oldbranch ^^newbranch --no-merges.
VonC

3
Cụ thể, nó hoạt động trong Windows trong bảng điều khiển Powershell, nhưng yêu cầu thêm "^" trong CMD.
Rod

7

Nếu đó là một (một) nhánh mà bạn cần kiểm tra, ví dụ nếu bạn muốn nhánh đó 'B' được hợp nhất hoàn toàn vào nhánh 'A', bạn chỉ cần thực hiện như sau:

$ git checkout A
$ git branch -d B

git branch -d <branchname> có sự an toàn rằng "Chi nhánh phải được hợp nhất hoàn toàn trong CHÍNH."

Thận trọng : điều này thực sự xóa nhánh B nếu nó được sáp nhập vào A.


3

Bạn có thể sử dụng tập lệnh đơn giản này để xem các cam kết không được hợp nhất

#!/bin/bash
# Show commits that exists only on branch and not in current
# Usage:
#   git branch-notmerge <branchname>
#
# Setup git alias
#   git config alias.branch-notmerge [path/to/this/script]
grep -Fvf <(git log --pretty=format:'%H - %s') <(git log $1 --pretty=format:'%H - %s')

Bạn cũng có thể sử dụng công cụ git-wtf sẽ hiển thị trạng thái của các nhánh


0

Chỉ cần sử dụng git cherryđể chọn tất cả các cam kết trong chi nhánh newFeature42chẳng hạn:

git cherry -v master newFeature42


-5

Bắt đầu tạo Yêu cầu kéo qua dịch vụ lưu trữ git bạn đang sử dụng. Nếu chi nhánh đã được hợp nhất hoàn toàn vào chi nhánh cơ sở, bạn sẽ không thể tạo PR mới.

Bạn không cần thực sự thực hiện yêu cầu kéo, chỉ cần sử dụng bước đầu tiên nơi bạn chọn chi nhánh.

Ví dụ: trên GitHub:

Không có gì để so sánh

Không thể tạo PR cho các chi nhánh đã được hợp nhất.

Điều này không sử dụng git trên dòng lệnh, nhưng tôi thường thấy hữu ích khi sử dụng các công cụ khác theo ý của bạn với một mô hình tinh thần rõ ràng hơn là cố gắng ghi nhớ một lệnh git phức tạp khá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.