Thẻ git là gì, Cách tạo thẻ & Cách kiểm tra (các) thẻ git từ xa


524

Khi tôi kiểm tra thẻ git từ xa, hãy sử dụng lệnh như thế này:

git checkout -b local_branch_name origin/remote_tag_name

Tôi đã gặp lỗi như thế này:

error: pathspec `origin/remote_tag_name` did not match any file(s) known to git.

Tôi có thể tìm thấy remote_tag_name khi tôi sử dụng lệnh thẻ git.

Câu trả lời:


1155

Hãy bắt đầu bằng cách giải thích thẻ trong git là gì

nhập mô tả hình ảnh ở đây

Một thẻ được sử dụng để gắn nhãn và đánh dấu một cam kết cụ thể trong lịch sử.
Nó thường được sử dụng để đánh dấu các điểm phát hành (ví dụ: v1.0, v.v.).

Mặc dù thẻ có thể xuất hiện tương tự như một nhánh , tuy nhiên, thẻ không thay đổi . Nó chỉ trực tiếp đến một cam kết cụ thể trong lịch sử.

nhập mô tả hình ảnh ở đây


Bạn sẽ không thể kiểm tra các thẻ nếu nó không cục bộ trong kho lưu trữ của bạn, vì vậy trước tiên, bạn phải fetchgắn thẻ vào kho lưu trữ cục bộ của mình.

Trước tiên, hãy chắc chắn rằng thẻ tồn tại cục bộ bằng cách thực hiện

# --all will fetch all the remotes.
# --tags will fetch all tags as well
$ git fetch --all --tags --prune

Sau đó kiểm tra thẻ bằng cách chạy

$ git checkout tags/<tag_name> -b <branch_name>

Thay vì originsử dụng tags/tiền tố.


Trong mẫu này, bạn có 2 thẻ phiên bản 1.0 & phiên bản 1.1, bạn có thể kiểm tra chúng với bất kỳ thẻ nào sau đây:

$ git checkout A  ...
$ git checkout version 1.0  ...
$ git checkout tags/version 1.0  ...

Tất cả những điều trên sẽ làm tương tự vì thẻ chỉ là một con trỏ tới một cam kết nhất định.

nhập mô tả hình ảnh ở đây
nguồn gốc: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


Làm thế nào để xem danh sách của tất cả các thẻ?

# list all tags
$ git tag

# list all tags with given pattern ex: v-
$ git tag --list 'v-*'

Làm thế nào để tạo thẻ?

Có 2 cách để tạo thẻ:

# lightweight tag 
$ git tag 

# annotated tag
$ git tag -a

Sự khác biệt giữa 2 là khi tạo thẻ chú thích, bạn có thể thêm siêu dữ liệu như bạn có trong một cam kết git:
tên, e-mail, ngày, nhận xét và chữ ký

nhập mô tả hình ảnh ở đây

Làm thế nào để xóa thẻ?

# delete any (local) given tag
$ git tag -d <tag name>

# Delete a tag from the server with push tags
$ git push --delete origin <tag name>

Làm thế nào để sao chép một thẻ cụ thể?

Để lấy nội dung của một thẻ nhất định, bạn có thể sử dụng checkoutlệnh. Như đã giải thích, các thẻ ở trên giống như bất kỳ cam kết nào khác, vì vậy chúng tôi có thể sử dụng checkoutvà thay vì sử dụng SHA-1 chỉ cần thay thế nó bằng tag_name

Lựa chọn 1:

# Update the local git repo with the latest tags from all remotes
$ git fetch --all

# checkout the specific tag
$ git checkout tags/<tag> -b <branch>

Lựa chọn 2:

Sử dụng lệnh clone

Vì git hỗ trợ clone nông bằng cách thêm --branchlệnh clone, chúng ta có thể sử dụng tên thẻ thay vì tên nhánh. Git biết cách "dịch" SHA-1 đã cho sang cam kết liên quan

# Clone a specific tag name using git clone 
$ git clone <url> --branch=<tag_name>

git clone --branch =

--branch cũng có thể lấy các thẻ và tách phần ĐẦU tại cam kết đó trong kho lưu trữ kết quả.


Làm thế nào để đẩy thẻ?

git push --tags

Để đẩy tất cả các thẻ:

# Push all tags
$ git push --tags 

Sử dụng refs/tagsthay vì chỉ xác định <tagname>.

Tại sao? - Bạn nên sử dụng refs/tagsvì đôi khi các thẻ có thể có cùng tên với các nhánh của bạn và git đẩy đơn giản sẽ đẩy nhánh thay vì thẻ

Để đẩy các thẻ chú thích và thẻ chuỗi lịch sử hiện tại, hãy sử dụng:

git push --follow-tags

Cờ này --follow-tagsđẩy cả hai cam kếtchỉ các thẻ là cả hai:

  • Các thẻ được chú thích (để bạn có thể bỏ qua các thẻ xây dựng cục bộ / temp)
  • Thẻ có thể truy cập (tổ tiên) từ chi nhánh hiện tại (nằm trong lịch sử)

nhập mô tả hình ảnh ở đây

Từ Git 2.4, bạn có thể thiết lập nó bằng cách sử dụng cấu hình

$ git config --global push.followTags true

Áo choàng: nhập mô tả hình ảnh ở đây



3
đẹp. git checkout A. là Agì Làm thế nào bạn tạo ra A?
Mật ong

3
@CodeWizard Biểu đồ luồng đẹp! Bạn đã sử dụng phần mềm nào để sản xuất nó?
Giovanni Lovato

4
@Honey Alà một hàm băm cam kết
Alex Baklanov

2
@GiovanniLovato Biểu đồ dòng chảy là của bên thứ ba. Liên kết đến hình ảnh là backlog.com/git-tutorial/img/post/stepup/ , từ trang này backlog.com/git-tutorial/stepup/stepup4_1.html của trang web có tên Git Begin 's Guide for Dummies (backlog .com).
George

2
Điều đáng chú ý là git checkout tags/<tag_name> -b <branch_name>không yêu cầu -b <branch_name>. git checkout tags/<tag_name>cho tôi một cái đầu tách ra Theo bài viết này về đầu tách ra , bạn tránh đầu tách ra bằng cách tạm thời tạo và xóa một nhánh. Đây là một luồng công việc ngoài hành tinh. Rõ ràng tôi là một người dùng git cần phải làm quen với việc tạo và xóa các chi nhánh để giải trí và kiếm lợi nhuận.
icc97

194

(Câu trả lời này mất một lúc để viết và câu trả lời của codeWizard đúng về mục tiêu và bản chất, nhưng không hoàn toàn đầy đủ, vì vậy tôi sẽ đăng bài này.)


Không có thứ gọi là "thẻ Git từ xa". Chỉ có "thẻ". Tôi chỉ tất cả ra đây không phải là gàn dở, 1 nhưng bởi vì có rất nhiều nhầm lẫn về điều này với những người dùng Git giản dị, và các tài liệu Git không phải là rất hữu ích 2 để bắt đầu. (Không rõ liệu sự nhầm lẫn xuất hiện do tài liệu kém hay tài liệu kém xuất hiện vì điều này vốn đã hơi khó hiểu hoặc là gì.)

"chi nhánh từ xa", gọi đúng hơn "chi nhánh từ xa theo dõi", nhưng nó đáng chú ý là thực tế đây là các đơn vị địa phương. Không có thẻ từ xa, mặc dù (trừ khi bạn (tái) phát minh ra chúng). Chỉ có các thẻ cục bộ, vì vậy bạn cần lấy thẻ cục bộ để sử dụng nó.

Biểu mẫu chung cho các tên cho các cam kết cụ thể mà Git gọi tham chiếu là bất kỳ chuỗi nào bắt đầu bằng refs/. Một chuỗi bắt đầu bằng refs/heads/tên một nhánh; một chuỗi bắt đầu bằng refs/remotes/tên một nhánh theo dõi từ xa; và một chuỗi bắt đầu bằng refs/tags/tên một thẻ. Tên refs/stashlà tham chiếu stash (như được sử dụng bởi git stash; lưu ý thiếu dấu gạch chéo).

Có một số bất thường tên đặc biệt hợp cụ thể mà không bắt đầu bằng refs/: HEAD, ORIG_HEAD, MERGE_HEAD, và CHERRY_PICK_HEADđặc biệt là tất cả cũng tên có thể tham khảo các cam kết cụ thể (mặc dù HEADthường chứa tên của một chi nhánh, tức là chứa ). Nhưng nói chung, tài liệu tham khảo bắt đầu với .ref: refs/heads/branchrefs/

Một điều Git làm để làm cho điều này trở nên khó hiểu là nó cho phép bạn bỏ qua refs/, và thường là từ sau refs/. Chẳng hạn, bạn có thể bỏ qua refs/heads/hoặc refs/tags/khi đề cập đến một chi nhánh địa phương hoặc gắn thẻ và thực tế bạn phải bỏ qua refs/heads/khi kiểm tra một chi nhánh địa phương! Bạn có thể làm điều này bất cứ khi nào kết quả không rõ ràng, hoặc vì chúng tôi chỉ lưu ý khi bạn phải làm điều đó (cho ).git checkout branch

Đúng là các tài liệu tham khảo không chỉ tồn tại trong kho lưu trữ của riêng bạn mà còn trong các kho lưu trữ từ xa. Tuy nhiên, Git cung cấp cho bạn quyền truy cập vào tài liệu tham khảo của kho lưu trữ từ xa vào những thời điểm rất cụ thể: cụ thể là, trong fetchpushhoạt động. Bạn cũng có thể sử dụng git ls-remotehoặc git remote showđể nhìn thấy chúng, nhưng fetchpushlà những điểm thú vị hơn tiếp xúc.

Giới thiệu

Trong fetchpush, Git sử dụng các chuỗi mà nó gọi là refspecs để chuyển các tham chiếu giữa kho lưu trữ cục bộ và từ xa. Do đó, chính tại thời điểm này và thông qua các refspec, hai kho Git có thể đồng bộ với nhau. Khi tên của bạn được đồng bộ hóa, bạn có thể sử dụng cùng tên mà một người có điều khiển từ xa sử dụng. Có một số phép thuật đặc biệt ở đây fetch, mặc dù, và nó ảnh hưởng đến cả tên nhánh và tên thẻ.

Bạn nên nghĩ đến git fetchviệc chỉ đạo Git của bạn gọi lên (hoặc có thể là tin nhắn văn bản) một Git khác, "từ xa" và có một cuộc trò chuyện với nó. Đầu cuộc trò chuyện này, từ xa liệt kê tất cả các tài liệu tham khảo của nó: mọi thứ trong refs/heads/và mọi thứ trong đó refs/tags/, cùng với bất kỳ tài liệu tham khảo nào khác mà nó có. Git của bạn quét qua những thứ này và (dựa trên refspec tìm nạp thông thường) đổi tên các nhánh của chúng.

Chúng ta hãy xem các refspec bình thường cho điều khiển từ xa có tên origin:

$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
$ 

Refspec này hướng dẫn Git của bạn lấy mọi tên trùng khớp refs/heads/*vớiieie, mọi chi nhánh trên điều khiển từ xa và thay đổi tên của nó thành refs/remotes/origin/*, giữ nguyên phần trùng khớp, thay đổi tên chi nhánh ( refs/heads/) thành tên chi nhánh theo dõi từ xa ( refs/remotes/cụ thể là , refs/remotes/origin/)

Thông qua refspec này , origincác nhánh của nó trở thành các nhánh theo dõi từ xa của bạn cho điều khiển từ xa origin. Tên chi nhánh trở thành tên chi nhánh theo dõi từ xa, với tên của điều khiển từ xa, trong trường hợp này origin, bao gồm. Dấu cộng +ở phía trước của refspec đặt cờ "lực lượng", nghĩa là nhánh theo dõi từ xa của bạn sẽ được cập nhật để khớp với tên nhánh của điều khiển từ xa, bất kể nó cần gì để khớp với nó. (Nếu không có +, cập nhật chi nhánh được giới hạn để "fast forward" thay đổi và cập nhật thẻ chỉ đơn giản là bỏ qua kể từ khi phiên bản Git 1.8.2 hoặc cái trước thì quy tắc tương tự nhanh về phía trước áp dụng.)

Thẻ

Nhưng những gì về thẻ? Không có refspec cho họ Ít nhất, không phải mặc định. Bạn có thể đặt một, trong trường hợp đó, hình thức của refspec tùy thuộc vào bạn; hoặc bạn có thể chạy git fetch --tags. Việc sử dụng --tagscó tác dụng thêm refs/tags/*:refs/tags/*vào refspec, nghĩa là, nó mang lại tất cả các thẻ ( nhưng không cập nhật thẻ của bạn nếu bạn đã có thẻ với tên đó, bất kể thẻ từ xa nói gì, Chỉnh sửa, tháng 1 năm 2017: kể từ Git 2.10 , kiểm tra cho thấy --tagsbuộc phải cập nhật các thẻ của bạn từ các thẻ của điều khiển từ xa, như thể refspec đã đọc +refs/tags/*:refs/tags/*, đây có thể là một sự khác biệt trong hành vi so với phiên bản Git trước đó).

Lưu ý rằng không có đổi tên ở đây: nếu điều khiển từ xa origincó thẻ xyzzyvà bạn không, và bạn git fetch origin "refs/tags/*:refs/tags/*", bạn sẽ được refs/tags/xyzzythêm vào kho lưu trữ của mình (trỏ đến cùng một cam kết như trên điều khiển từ xa). Nếu bạn sử dụng +refs/tags/*:refs/tags/*thì thẻ của bạn xyzzy, nếu bạn có, được thay thế bằng thẻ từ origin. Đó là, +cờ lực trên một refspec có nghĩa là "thay thế giá trị tham chiếu của tôi bằng giá trị Git của tôi nhận được từ Git của họ".

Thẻ tự động trong quá trình tìm nạp

Vì lý do lịch sử, 3 nếu bạn sử dụng --tagstùy chọn cũng không phải --no-tagstùy chọn, git fetchsẽ có hành động đặc biệt. Hãy nhớ rằng chúng tôi đã nói ở trên rằng điều khiển từ xa bắt đầu bằng cách hiển thị cho Git cục bộ của bạn tất cả các tham chiếu của nó, cho dù Git cục bộ của bạn có muốn xem chúng hay không. 4 Git của bạn ghi chú tất cả các thẻ mà nó nhìn thấy tại thời điểm này. Sau đó, khi nó bắt đầu tải xuống bất kỳ đối tượng cam kết nào, nó cần xử lý bất cứ thứ gì nó tìm nạp, nếu một trong những cam kết đó có cùng ID với bất kỳ thẻ nào, git sẽ thêm thẻ đó hoặc các thẻ đó, nếu nhiều thẻ có ID ID đó vào kho lưu trữ của bạn.

Chỉnh sửa, tháng 1 năm 2017: thử nghiệm cho thấy các hành vi trong Git 2.10 bây giờ là: Nếu Git của họ cung cấp một thẻ tên T , bạn không có một thẻ tên T , cam kết ID kết hợp với T là tổ tiên của một trong những chi nhánh của họ rằng bạn git fetchđang kiểm tra, Git của bạn thêm T vào thẻ của bạn có hoặc không có --tags. Việc thêm --tagskhiến Git của bạn có được tất cả các thẻ của họ và cũng buộc phải cập nhật.

Dòng dưới cùng

Bạn có thể phải sử dụng git fetch --tagsđể có được thẻ của họ. Nếu tên thẻ của chúng xung đột với tên thẻ hiện tại của bạn, bạn có thể (tùy thuộc vào phiên bản Git) thậm chí phải xóa (hoặc đổi tên) một số thẻ của mình, sau đó chạy git fetch --tags, để lấy thẻ của chúng. Vì các thẻ mà không giống như các chi nhánh từ xa, nên không có việc đổi tên tự động, tên thẻ của bạn phải khớp với tên thẻ của chúng, đó là lý do tại sao bạn có thể gặp sự cố với xung đột.

Tuy nhiên, trong hầu hết các trường hợp thông thường, một người đơn giản git fetchsẽ thực hiện công việc, mang lại các cam kết và thẻ phù hợp của họ, và vì họ là bất cứ ai, họ sẽ gắn thẻ vào thời điểm họ công bố các cam kết đó, bạn sẽ theo kịp các thẻ của họ. Nếu bạn không tạo các thẻ của riêng mình, cũng không trộn lẫn kho lưu trữ của chúng và các kho lưu trữ khác (thông qua nhiều điều khiển từ xa), bạn sẽ không có bất kỳ xung đột tên thẻ nào, vì vậy bạn sẽ không phải loay hoay với việc xóa hoặc đổi tên thẻ để có được thẻ của họ.

Khi bạn cần tên đủ điều kiện

Tôi đã đề cập ở trên mà bạn có thể bỏ qua refs/hầu như mọi khi, và refs/heads/refs/tags/và vân vân hầu hết thời gian. Nhưng khi nào bạn không thể ?

Các (anyway hoặc gần như hoàn chỉnh) hoàn chỉnh câu trả lời là trong các gitrevisionstài liệu hướng dẫn . Git sẽ phân giải tên thành ID cam kết bằng chuỗi sáu bước được đưa ra trong liên kết. Thật kỳ lạ, các thẻ ghi đè lên các nhánh: nếu có một thẻ xyzzyvà một nhánh xyzzyvà chúng trỏ đến các cam kết khác nhau, thì:

git rev-parse xyzzy

sẽ cung cấp cho bạn ID mà thẻ trỏ tới. Tuy nhiên, và đây là thứ còn thiếu gitrevisions- git checkoutthích tên chi nhánh, vì vậy git checkout xyzzysẽ đưa bạn vào chi nhánh, bỏ qua thẻ.

Trong trường hợp không rõ ràng, bạn hầu như luôn có thể đánh vần tên ref bằng tên đầy đủ của nó, refs/heads/xyzzyhoặc refs/tags/xyzzy. (Lưu ý rằng điều này không làm việc với git checkout, nhưng trong một cách có lẽ bất ngờ: git checkout refs/heads/xyzzylàm một kiểm tra tách ra-HEAD chứ không phải là kiểm tra chi nhánh Đây là lý do tại sao bạn chỉ cần lưu ý đó. git checkoutSẽ sử dụng tên viết tắt như một tên chi nhánh đầu tiên: đó là cách bạn kiểm tra chi nhánh xyzzyngay cả khi thẻ xyzzytồn tại. Nếu bạn muốn kiểm tra thẻ, bạn có thể sử dụng refs/tags/xyzzy.)

Bởi vì (như gitrevisionsghi chú) Git sẽ thử , bạn cũng có thể viết đơn giản để xác định cam kết được gắn thẻ . (Nếu ai đó đã cố gắng viết một tham chiếu hợp lệ tên vào , tuy nhiên, điều này sẽ giải quyết như . Nhưng thường chỉ khác nhau tên phải ở trong .)refs/nametags/xyzzyxyzzyxyzzy$GIT_DIR$GIT_DIR/xyzzy*HEAD$GIT_DIR


1 Được rồi, được rồi, "không chỉ là phạm tội". :-)

2 Một số người sẽ nói "rất không hữu ích", và tôi thực sự có xu hướng đồng ý.

3 Về cơ bản, git fetchvà toàn bộ khái niệm từ xa và refspecs, là một chút bổ sung muộn cho Git, xảy ra vào khoảng thời gian của Git 1.5. Trước đó, chỉ có một số trường hợp đặc biệt đặc biệt, và tìm nạp thẻ là một trong số đó, vì vậy nó đã được mở rộng thông qua mã đặc biệt.

4 Nếu có ích, hãy nghĩ về Git từ xa như một flasher , theo nghĩa tiếng lóng.


Tuyệt vời viết. Một nit nhỏ: git fetchsẽ chỉ tìm nạp các thẻ của điều khiển từ xa --tags.
vào

@cweekly: hành vi của --tags, --no-tagsvà mặc định là thực sự khá phức tạp. Mặc định là mang các thẻ mà bạn không có trong các cam kết mà bạn mang đến. (Xem bản chỉnh sửa tháng 1 năm 2017.) Nhưng cũng có những trục trặc ở đây và Git hiện đại đang có --tags / --no-tags xử lý mã được sửa đổi một lần nữa, điều này có thể sẽ dẫn đến các trường hợp góc đặc biệt hơn.

1

Để kiểm tra thẻ git, bạn sẽ thực hiện lệnh sau

git checkout tags/tag-name -b branch-name

ví dụ như được đề cập dưới đây.

 git checkout tags/v1.0 -b v1.0-branch

Để tìm nạp tất cả các thẻ, sử dụng lệnh

git fetch --all --tags

0

Để có được mã thẻ cụ thể, hãy thử tạo một nhánh mới, thêm lấy mã thẻ trong đó. Tôi đã thực hiện nó bằng lệnh:$git checkout -b newBranchName tagName

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.