Làm cách nào để có được tên thẻ mới nhất trong chi nhánh hiện tại trong Git?


462

Cách đơn giản nhất để có thẻ gần đây nhất trong Git là gì?

git tag a HEAD
git tag b HEAD^^
git tag c HEAD^
git tag

đầu ra:

a
b
c

Tôi có nên viết một tập lệnh để lấy datetime của mỗi thẻ và so sánh chúng không?


1
thẻ được tạo mới nhất hoặc thẻ mới nhất được sắp xếp theo ngày cam kết? Câu trả lời được chấp nhận của bạn cho thấy thẻ được tạo mới nhất. Đây có thể là một vấn đề nếu một người quyết định thay đổi các thẻ tồn tại ...
Paebbels

Câu trả lời:


412

Bạn có thể xem git describe, cái mà gần với những gì bạn đang hỏi.


194
Với --abbrev=0nó sẽ trả lại thẻ chú thích gần nhất
Jakub Narębski

13
Trả về thẻ mới nhất trong nhánh hiện tại.
brittohalloran

42
Để có thẻ chú thích mới nhất chỉ nhắm vào cam kết hiện tại trong nhánh hiện tại , hãy sử dụng git describe --exact-match --abbrev=0.
Naftuli Kay

5
Câu trả lời này, với ý kiến, đã không cung cấp thẻ chính xác cho tôi. @kilianic cung cấp một giải pháp chính xác.
Herman J. Radtke III

19
git describe --tagsvà so sánh thẻ cuối cùng trong trang phát hành github
Adriano Resende

627

Để có được thẻ gần đây nhất:

git describe --tags

Để có được thẻ chú thích gần đây nhất :

git describe --abbrev=0

2
Đúng, như trang người đàn ông đã git describenói: --abbrev=<n> [...] An <n> of 0 will suppress long format, only showing the closest tag.
Giorgos Kylafas

22
Hoặc chỉgit describe --tags
james_womack

5
Câu trả lời này (và có thể là các câu hỏi khác) gặp rắc rối nếu bạn có hai thẻ trỏ đến cùng một cam kết. Trừ khi các thẻ là các thẻ chú thích, tôi nghĩ không có cách nào để git phân biệt cái nào trong hai cái được tạo ra trước đó.
Paul Lynch

10
Đây phải là câu trả lời được chấp nhận. Cảm ơn đã gửi.
crmpicco

6
nếu bạn muốn trực tiếp kiểm tra thẻ gần đây nhất:git checkout $(git describe --abbrev=0 --tags)
JohnRDOrazio

321

Sẽ xuất thẻ của cam kết được gắn thẻ mới nhất trên tất cả các chi nhánh

git describe --tags $(git rev-list --tags --max-count=1)

8
hoặc TAG=$(git describe --tags $(git rev-list --tags --max-count=1))@ william-pursell
kilianc

20
Đây là câu trả lời tốt nhất. Nó thực sự có các thẻ trên tất cả các chi nhánh, không chỉ chi nhánh hiện tại, giống như câu trả lời "chính xác" hiện tại.
brittohalloran

61
Ngoại trừ câu hỏi đặc biệt yêu cầu chi nhánh hiện tại.
michaeltwofish

3
@michaeltwofish, tại thời điểm tôi không biết điều đó, tôi đã tìm ra nó sau đó và sửa câu trả lời của mình. Xin lỗi vì điều đó.
kilianc

3
Ghi chú: Lệnh này trả về thẻ "mới nhất" ngay cả thẻ này nằm trên nhánh khác.
Alan Zhiliang Feng 16/07/2015

47

Để có được thẻ gần đây nhất, bạn có thể làm:

$ git for-Each-ref refs / tags --sort = -taggerdate --format = '% (refname)' --count = 1

Tất nhiên, bạn có thể thay đổi đối số đếm hoặc trường sắp xếp theo ý muốn. Có vẻ như bạn có thể có ý định hỏi một câu hỏi hơi khác, nhưng điều này không trả lời câu hỏi khi tôi diễn giải nó.


2
Đây gần như chính xác là thứ tôi đang tìm kiếm (thẻ gần đây nhất trên tất cả các chi nhánh), nhưng ít nhất là với phiên bản git của tôi (1.7.7.6), các thẻ được sản xuất theo cùng một thứ tự cho cả hai --sort=-authordate--sort=authordate.
larsks

3
Aha, bởi vì những gì bạn thực sự muốn là --sort=-taggerdate. Đối với các thẻ authordatecommitterdatetrống (vì vậy vô dụng như các phím sắp xếp).
larsks

8
git for-each-ref refs/tags --sort=-taggerdate --format='%(refname:short)' --count=1thậm chí còn tốt hơn :)
Barshe Eblé

5
Thực sự, hạ thấp một câu trả lời hoàn toàn chính xác mà gần 5 tuổi mà không có nhận xét? Điều đó thật thô lỗ.
William Pursell

1
--points-at=$SHAsẽ cung cấp cho bạn thẻ cho một băm cam kết.
Ryan

35

Còn cái này thì sao?

TAG=$(git describe $(git rev-list --tags --max-count=1))

Về mặt kỹ thuật, sẽ không nhất thiết phải có cho bạn thẻ mới nhất, nhưng cam kết mới nhất được gắn thẻ, có thể hoặc không phải là thứ bạn đang tìm kiếm.


Cái này không nhận được thẻ mới nhất trong nhánh hiện tại nhưng cho bất kỳ nhánh nào. Điều đó thật tuyệt, vì đó chính xác là những gì tôi cần. Cảm ơn Wincent.
jasongregori

2
Nếu bạn cần phải nhận được mẫu thẻ phù hợp bạn có thể sử dụng --tags=<pattern>trong rev-list. Ví dụ: lấy thẻ phiên bản cuối cùnggit describe --tags $(git rev-list --tags='v[0-9].[0-9]*' --max-count=1)
Wirone

1
$ (mô tả git - liên quan $ (git rev-parse HEAD))
Vaidas Zilionis

Cảm ơn, nó đã hoạt động, nhưng, tôi đã phải thêm --tags git describe --tags $(git rev-list --tags --max-count=1)
Gianluca Casati

25

Bạn có thể thực thi: git describe --tags $(git rev-list --tags --max-count=1)đã nói ở đây: Làm thế nào để có được tên thẻ mới nhất?


Tôi bắt đầu với câu trả lời hàng đầu / được chấp nhận và làm việc theo cách của tôi. Đây là câu trả lời đầu tiên thực sự mang lại cho tôi thẻ mới nhất (không rõ tại sao nhưng cũ đơn giản git describe ...trả lại thẻ trước đó?!)
Jeremy Davis

Đây là người duy nhất làm việc cho tôi. Đã thử một số --abbrev=0câu trả lời và họ đã cắt bỏ một phần của thẻ mà tôi muốn.
Luke Davis

22

"Gần đây nhất" có thể có hai ý nghĩa về mặt git.

Bạn có thể có nghĩa là "thẻ nào có ngày tạo mới nhất trong thời gian" và hầu hết các câu trả lời ở đây là dành cho câu hỏi đó. Về câu hỏi của bạn, bạn sẽ muốn trả lại thẻ c.

Hoặc bạn có thể có nghĩa là "thẻ nào là gần nhất trong lịch sử phát triển với một số nhánh được đặt tên", thường là nhánh bạn đang ở , HEAD. Trong câu hỏi của bạn, điều này sẽ trả về thẻa .

Tất nhiên đây có thể khác nhau:

A->B->C->D->E->F (HEAD)
       \     \
        \     X->Y->Z (v0.2)
         P->Q (v0.1)

Hãy tưởng tượng các nhà phát triển tag'ed Znhư v0.2vào thứ hai, và sau đó tag'ed Qnhư v0.1hôm thứ Ba. v0.1là gần đây hơn, nhưng v0.2gần hơn trong lịch sử phát triển với HEAD, theo nghĩa là con đường mà nó đang đi bắt đầu tại một điểm gần hơn với HEAD.

Tôi nghĩ bạn thường muốn câu trả lời thứ hai này, gần hơn trong lịch sử phát triển. Bạn có thể tìm thấy điều đó bằng cách sử dụng git log v0.2..HEADvv cho mỗi thẻ. Điều này cung cấp cho bạn số lần xác nhận trên HEAD kể từ khi đường dẫn kết thúc tạiv0.2 chuyển hướng từ đường dẫn theo sau là HEAD.

Đây là tập lệnh Python thực hiện điều đó bằng cách lặp qua tất cả các thẻ đang chạy kiểm tra này, sau đó in ra thẻ với ít lần xác nhận nhất trên HEAD vì đường dẫn thẻ được chuyển hướng:

https://github.com/MacPython/terryfy/blob/master/git-closest-tag

git describethực hiện một cái gì đó hơi khác, trong đó nó theo dõi lại từ (ví dụ) ĐẦU để tìm thẻ đầu tiên nằm trên đường dẫn trong lịch sử từ HEAD. Theo thuật ngữ git, hãy git describetìm các thẻ "có thể truy cập" từ HEAD. Do đó, nó sẽ không tìm thấy các thẻ như thế v0.2không nằm trên đường dẫn trở lại từ HEAD, mà là một đường dẫn được chuyển hướng từ đó.


21

git describe --tags

trả về thẻ cuối cùng có thể được nhìn thấy bởi chi nhánh hiện tại


15
git log --tags --no-walk --pretty="format:%d" | sed 2q | sed 's/[()]//g' | sed s/,[^,]*$// | sed  's ......  '

NẾU BẠN CẦN THÊM MỘT M TAG THỜI GIAN

(mô tả git - đôi khi đưa ra các giá trị băm sai, tôi không biết tại sao, nhưng đối với tôi - max-Count 2 không hoạt động)

đây là cách bạn có thể nhận danh sách với 2 tên thẻ mới nhất theo thứ tự thời gian đảo ngược, hoạt động hoàn hảo trên git 1.8.4. Đối với các phiên bản trước của git (như 1.7. *), Không có chuỗi "tag:" trong đầu ra - chỉ cần xóa cuộc gọi sed cuối cùng

Nếu bạn muốn có nhiều hơn 2 thẻ mới nhất - hãy thay đổi "sed 2q" này thành "sed 5q" hoặc bất cứ thứ gì bạn cần

Sau đó, bạn có thể dễ dàng phân tích từng tên thẻ thành biến.


Điều này thực sự hữu ích, nhiều nhà phát triển sẽ cố gắng tự động hóa quy trình phát hành bằng cách quay lại thẻ trước nếu triển khai bị phá vỡ. Tuyệt vời thứ !!!
AkD

1
Để thực hiện điều này hơn nữa: git log --tags --no-walk --pretty="format:%D" | sed -nr '5q;s;^.*(tag: )([^,]*).*;\2;p' trong đó %Dloại trừ các ()ký tự xung quanh và sed5q bắt đầu để lại 4 dòng trước 5, sau đó in ra tất cả các ký tự giữa 'tag: `và đầu tiên', '. Vì vậy, ... giả sử không có dấu phẩy được sử dụng trong thẻ, điều này hoạt động hoàn hảo.
Cometsong

14

Có gì sai với tất cả các đề xuất (ngoại trừ Matthew Brett lời giải thích của , đến ngày của bài trả lời này)?

Chỉ cần chạy bất kỳ lệnh nào được cung cấp bởi người khác trên lịch sử jQuery Git khi bạn ở điểm lịch sử khác nhau và kiểm tra kết quả với biểu diễn lịch sử gắn thẻ trực quan (Tôi đã làm đó là lý do tại sao bạn thấy bài đăng này):

$ git log --graph --all --decorate --oneline --simplify-by-decoration

Ngày nay, nhiều dự án thực hiện các bản phát hành (và do đó gắn thẻ) trong nhánh riêng biệt từ dòng chính .

lý do mạnh mẽ cho việc này. Chỉ cần nhìn vào bất kỳ dự án JS / CSS nào được thiết lập tốt. Đối với quy ước người dùng, họ mang các tệp phát hành nhị phân / rút gọn trong DVCS. Một cách tự nhiên như duy trì dự án bạn không muốn rác đường chính của bạn diff lịch sử với các đốm màu nhị phân vô dụng và thực hiện các cam kết hợp đồng xây dựng hiện vật ra khỏi đường chính .

Bởi vì Git sử dụng DAG chứ không phải lịch sử tuyến tính - thật khó để xác định số liệu khoảng cách nên chúng tôi có thể nói - ồ đó là rev gần nhất với tôi HEAD!

Tôi bắt đầu hành trình của riêng mình (nhìn vào bên trong, tôi đã không sao chép những hình ảnh bằng chứng lạ mắt vào bài đăng dài này):

Thẻ gần nhất trong quá khứ liên quan đến phân nhánh trong Git là gì?

Hiện tại tôi có 4 định nghĩa hợp lý về khoảng cách giữa thẻ và sửa đổi với mức độ hữu dụng giảm dần:

  • độ dài của con đường ngắn nhất từ HEADđể hợp nhất cơ sở với thẻ
  • ngày của cơ sở hợp nhất giữa HEADvà thẻ
  • số vòng quay có thể truy cập từ CHÍNH nhưng không thể truy cập từ thẻ
  • ngày của thẻ bất kể cơ sở hợp nhất

Tôi không biết cách tính chiều dài của con đường ngắn nhất .

Script rằng các thẻ loại theo ngày của cơ sở hợp nhất giữa HEADvà gắn thẻ:

$ git tag \
     | while read t; do \
         b=`git merge-base HEAD $t`; \
         echo `git log -n 1 $b --format=%ai` $t; \
       done | sort

Nó có thể sử dụng trên hầu hết các dự án.

Script rằng các thẻ loại theo số vòng quay mà có thể truy cập từ TRỤ nhưng không thể truy cập từ thẻ:

$ git tag \
    | while read t; do echo `git rev-list --count $t..HEAD` $t; done \
    | sort -n

Nếu lịch sử dự án của bạn có ngày lạ trên các cam kết (vì các cuộc nổi loạn hoặc viết lại lịch sử khác hoặc một số moron quên thay pin BIOS hoặc các phép thuật khác mà bạn làm trong lịch sử), hãy sử dụng tập lệnh trên.

Đối với tùy chọn cuối cùng ( ngày của thẻ bất kể cơ sở hợp nhất ) để có danh sách các thẻ được sắp xếp theo ngày sử dụng:

$ git log --tags --simplify-by-decoration --pretty="format:%ci %d" | sort -r

Để biết ngày sửa đổi hiện tại, hãy sử dụng:

$ git log --max-count=1

Lưu ý rằng git describe --tagscó sử dụng trong các trường hợp riêng của mình nhưng không tìm thấy thẻ gần nhất dự kiến ​​của con người trong lịch sử dự án .

LƯU Ý Bạn có thể sử dụng các công thức trên ở bất kỳ sửa đổi nào, chỉ cần thay thế HEADbằng những gì bạn muốn!


12

git describe --abbrev=0 --tags

Nếu bạn không thấy thẻ mới nhất, hãy đảm bảo tìm nạp nguồn gốc trước khi chạy:

git remote update


12
git tag -l ac* | tail -n1

Lấy thẻ cuối cùng với tiền tố "ac" . Ví dụ: thẻ có tên ac1.0.0, hoặc ac1.0.5. Các thẻ khác được đặt tên 1.0.0, 1.1.0sẽ bị bỏ qua.

git tag -l [0-9].* | tail -n1

Lấy thẻ cuối cùng, có char đầu tiên 0-9. Vì vậy, những thẻ với char đầu tiêna-z sẽ bị bỏ qua.

Thêm thông tin

git tag --help # Help for `git tag`

git tag -l <pattern>

Liệt kê các thẻ có tên khớp với mẫu đã cho (hoặc tất cả nếu không có mẫu nào được cung cấp). Chạy "thẻ git" không có đối số cũng liệt kê tất cả các thẻ. Mẫu này là ký tự đại diện shell (nghĩa là được khớp bằng fnmatch (3)). Nhiều mẫu có thể được đưa ra; nếu bất kỳ trong số chúng phù hợp, thẻ được hiển thị.


tail -n <number> # display the last part of a file
tail -n1 # Display the last item 

Cập nhật

Với git tag --help, về sorttranh luận. Nó sẽ sử dụng lexicorgraphic ordertheo mặc định, nếu thuộc tag.sorttính không tồn tại.

Sắp xếp thứ tự mặc định cho giá trị được cấu hình cho biến tag.sort nếu nó tồn tại hoặc theo thứ tự từ điển khác. Xem git-config (1).

Sau google, có người nói git 2.8.0 hỗ trợ cú pháp theo sau.

git tag --sort=committerdate

Nó không phù hợp với tôi, thẻ cuối cùng là 2.11.174 nhưng bản in này là 2.11.99 vì sắp xếp không phải là phiên bản
Ali.MD

8
git tag --sort=committerdate | tail -1

Vui lòng giải thích cách đoạn mã này sẽ giải quyết vấn đề, thay vì đăng câu trả lời chỉ mã.
Arun Vinoth

5

Các công việc sau đây cho tôi trong trường hợp bạn cần hai thẻ cuối cùng (ví dụ: để tạo nhật ký thay đổi giữa thẻ hiện tại và thẻ trước đó). Tôi đã thử nghiệm nó chỉ trong tình huống thẻ mới nhất là HEAD.

PreviousAndCurrentGitTag=`git describe --tags \`git rev-list --tags --abbrev=0 --max-count=2\` --abbrev=0`
PreviousGitTag=`echo $PreviousAndCurrentGitTag | cut -f 2 -d ' '`
CurrentGitTag=`echo $PreviousAndCurrentGitTag | cut -f 1 -d ' '`

GitLog=`git log ${PreviousGitTag}..${CurrentGitTag} --pretty=oneline | sed "s_.\{41\}\(.*\)_; \1_"`

Nó phù hợp với nhu cầu của tôi, nhưng vì tôi không phải là phù thủy git, tôi chắc chắn rằng nó có thể được cải thiện hơn nữa. Tôi cũng nghi ngờ nó sẽ bị phá vỡ trong trường hợp lịch sử cam kết tiến lên. Tôi chỉ chia sẻ trong trường hợp nó giúp được ai đó.


4

Suy nghĩ đầu tiên của tôi là bạn có thể sử dụng git rev-list HEAD, trong đó liệt kê tất cả các vòng quay theo thứ tự thời gian đảo ngược, kết hợp với git tag --contains. Khi bạn tìm thấy một ref nơi git tag --containstạo ra một danh sách không trống, bạn đã tìm thấy (các) thẻ gần đây nhất.


4

Nếu bạn muốn tìm thẻ cuối cùng được áp dụng trên một nhánh cụ thể, bạn có thể thử như sau:

git describe --tag $(git rev-parse --verify refs/remotes/origin/"branch_name")

3

Nếu bạn cần một lớp lót có tên thẻ mới nhất (theo ngày thẻ) trên nhánh hiện tại :

git for-each-ref refs/tags --sort=-taggerdate --format=%(refname:short) --count=1 --points-at=HEAD

Chúng tôi sử dụng điều này để đặt số phiên bản trong thiết lập.

Ví dụ đầu ra:

v1.0.0

Hoạt động trên Windows cũng vậy.


1
Trên Linux (Debian Stretch) tôi nhận được-bash: syntax error near unexpected token '('
Jeremy Davis

1
Nếu tôi gói phần đó trong dấu ngoặc kép (tức là --format="%(refname:short)") và bỏ qua phần --points-at=HEADđó hoạt động. Với công tắc cuối cùng đó, nó không trả về gì cả, tôi đoán vì tôi HEADkhông được gắn thẻ?
Jeremy Davis

@JeremyDavis, vâng tôi nghĩ đó là vì bạn HEADkhông được gắn thẻ.
Markus

2

Đây là một chủ đề cũ, nhưng có vẻ như nhiều người đang thiếu câu trả lời đơn giản nhất, dễ nhất và đúng nhất cho câu hỏi của OP: để có được thẻ mới nhất cho chi nhánh hiện tại , bạn sử dụng git describe HEAD. Làm xong.

Chỉnh sửa: bạn cũng có thể cung cấp bất kỳ tên gọi hợp lệ, thậm chí từ xa; tức là, git describe origin/mastersẽ cho bạn biết thẻ mới nhất có thể đạt được từ origin / master.


Không có gì đảm bảo rằng "thẻ gần đây nhất" được xử lý bởi bất kỳ chi nhánh nào. Hai giải pháp làm việc là for-each-reflệnh ( stackoverflow.com/a/5261470/515973 ) và sự kết hợp của rev-listdescribe( stackoverflow.com/a/7979255/515973 )
Julien Carsique

1
Điều này không nhận được thẻ gần đây nhất cho tôi.
K - Độc tính trong SO đang tăng lên.

git describe branchname --tags không hoạt động để tôi có được thẻ mới nhất trên chi nhánh (phiên bản git 2.12.2)
Rob_M

0

Để chỉ nhận được thẻ mới nhất trên tên chi nhánh / thẻ hiện tại có tiền tố với chi nhánh hiện tại, tôi đã phải thực hiện như sau

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags --abbrev=0 $BRANCH^ | grep $BRANCH

Chủ chi nhánh:

git checkout master

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags 
--abbrev=0 $BRANCH^ | grep $BRANCH

master-1448

Chi nhánh tùy chỉnh:

git checkout 9.4

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags 
--abbrev=0 $BRANCH^ | grep $BRANCH

9.4-6

Và nhu cầu cuối cùng của tôi là tăng và lấy thẻ +1 để gắn thẻ tiếp theo.

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags  --abbrev=0 $BRANCH^ | grep $BRANCH | awk -F- '{print $NF}'

0

Đối với câu hỏi như đã hỏi,

Làm thế nào để có được tên thẻ mới nhất trong chi nhánh hiện tại

bạn muốn

git log --first-parent --pretty=%d | grep -m1 tag:

--first-parentnói git logkhông chi tiết bất kỳ lịch sử hợp nhất, --pretty=%dnói chỉ hiển thị các trang trí tức là tên địa phương cho bất kỳ cam kết. grep -m1nói "khớp chỉ một", vì vậy bạn chỉ nhận được thẻ gần đây nhất.


0

nếu thẻ của bạn có thể sắp xếp:

git tag --merged $YOUR_BRANCH_NAME | grep "prefix/" | sort | tail -n 1

0

Không đề cập nhiều đến các thẻ không được quản lý so với các thẻ chú thích ở đây. 'mô tả' hoạt động trên các thẻ chú thích và bỏ qua các thẻ không được chú ý.

Điều này là xấu nhưng công việc được yêu cầu và nó sẽ không tìm thấy bất kỳ thẻ nào trên các nhánh khác (và không phải trên một thẻ được chỉ định trong lệnh: master trong ví dụ dưới đây)

Việc lọc nên được tối ưu hóa (hợp nhất), nhưng một lần nữa, điều này dường như với công việc.

git log  --decorate --tags master |grep '^commit'|grep 'tag:.*)$'|awk '{print $NF}'|sed 's/)$//'|head -n 1

Các nhà phê bình hoan nghênh vì tôi sẽ sử dụng nó ngay bây giờ :)


-2

Một cách đơn giản khác để có được tên thẻ mới nhất là với

git tag | tail -1

hoặc là

TAG=$(git tag | tail -1)

để lưu trữ nó trong một biến.

git tagliệt kê tất cả các thẻ có sẵn và sẽ trả về hàng cuối cùng nếu kết quả.tail-1


4
Không sắp xếp, đây là một động thái xấu.
mjd2
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.