Thẻ khác với chi nhánh trong Git như thế nào? Tôi nên sử dụng cái nào ở đây?


616

Tôi gặp một số khó khăn trong việc hiểu cách sử dụng thẻ so với các chi nhánh trong.

Tôi vừa chuyển phiên bản hiện tại của mã của chúng tôi từ đến và bây giờ tôi sẽ làm việc với một tập hợp con của mã đó cho một tính năng cụ thể. Một vài nhà phát triển khác cũng sẽ làm việc với điều này, nhưng không phải tất cả các nhà phát triển trong nhóm của chúng tôi sẽ quan tâm đến tính năng này. Tôi nên tạo một chi nhánh hoặc một thẻ? Trong những tình huống tôi nên sử dụng cái này so với cái kia?


4
Vì tìm kiếm trên web về cách sử dụng thẻ git đã đưa tôi đến liên kết đó trước tiên, tôi thêm rằng có một câu trả lời (IMHO) tốt hơn về một thẻ ở đây: stackoverflow.com/questions/35979642/
trộm

Câu trả lời:


520

Một thẻ đại diện cho một phiên bản của một chi nhánh cụ thể tại một thời điểm. Một nhánh đại diện cho một chuỗi phát triển riêng biệt có thể chạy đồng thời với các nỗ lực phát triển khác trên cùng một cơ sở mã. Thay đổi đối với một chi nhánh cuối cùng có thể được sáp nhập trở lại vào một chi nhánh khác để thống nhất chúng.

Thông thường, bạn sẽ tag một phiên bản đặc biệt để bạn có thể tạo lại nó, ví dụ, đây là phiên bản chúng tôi vận chuyển đến XYZ Corp . Một nhánh là một chiến lược nhằm cung cấp các bản cập nhật đang diễn ra trên một phiên bản mã cụ thể trong khi tiếp tục phát triển nó Bạn sẽ tạo một nhánh của phiên bản được phân phối, tiếp tục phát triển trên dòng chính, nhưng thực hiện sửa lỗi cho nhánh đại diện cho phiên bản được phân phối. Cuối cùng, bạn sẽ hợp nhất các bản sửa lỗi này vào dòng chính. Thường thì bạn sẽ sử dụng cả phân nhánh và gắn thẻ với nhau. Bạn sẽ có nhiều thẻ khác nhau có thể áp dụng cho cả dòng chính và các nhánh của nó đánh dấu các phiên bản cụ thể (ví dụ: được phân phối cho khách hàng) dọc theo mỗi chi nhánh mà bạn có thể muốn tạo lại - để phân phối, chẩn đoán lỗi, v.v.

Nó thực sự phức tạp hơn thế này - hoặc phức tạp như bạn muốn thực hiện - nhưng những ví dụ này sẽ cho bạn ý tưởng về sự khác biệt.


40
trong trường hợp của anh ấy, anh ấy muốn sử dụng các nhánh, có lẽ bạn cũng nên lưu ý điều này trong câu trả lời của bạn;)
knittl

13
AFAIK, thẻ không phải là duy nhất cho mỗi chi nhánh. Vì vậy, bạn không thể đặt tên giống nhau cho các cam kết khác nhau trong các nhánh riêng biệt.
MY

5
@MY Chắc chắn không phải là một điều xấu, IMHO. Đặc biệt theo cách được mô tả bởi tvanfosson, việc có nhiều hơn một thẻ có cùng tên trên các nhánh khác nhau có thể trở nên khó duy trì. Lấy ví dụ, tôi sẽ nghĩ rằng nếu bạn có thể có các thẻ có cùng tên trên các nhánh khác nhau, nó sẽ nhanh chóng được thiết lập như một thực tiễn xấu. Thật tốt khi biết rằng bạn không thể, mặc dù. Cảm ơn tôi!
Xoay

28
Thẻ chỉ là bí danh cho hàm băm cam kết. Tương tự như bạn có thể kiểm tra một cam kết với git checkout 88c9f229fbạn có thể làm một cái gì đó giống như git checkout your_tagvà bạn sẽ kiểm tra các cam kết đã được đặt bí danh bởi thẻ.
jterm

6
@jterm, không phải là bí danh chi nhánh quá? Sự khác biệt duy nhất là một bí danh chi nhánh tự động bổ sung chính nó vào cam kết gần đây nhất trong chuỗi.
Viktor Molokostov

529

Từ quan điểm lý thuyết :

  • thẻ là tên tượng trưng cho một sửa đổi nhất định . Họ luôn chỉ đến cùng một đối tượng (thường là: sửa đổi giống nhau); họ không thay đổi.
  • chi nhánh là tên tượng trưng cho dòng phát triển . Cam kết mới được tạo ra trên đầu chi nhánh. Con trỏ nhánh tự nhiên tiến lên, trỏ đến các xác nhận mới hơn và mới hơn.

Từ quan điểm kỹ thuật :

  • các thẻ nằm trong refs/tags/không gian tên và có thể trỏ đến các đối tượng thẻ (thẻ có ký hiệu GPG được chú thích và tùy chọn) hoặc trực tiếp để cam kết đối tượng (thẻ nhẹ ít được sử dụng cho tên cục bộ) hoặc trong các trường hợp rất hiếm ngay cả đối tượng cây hoặc đối tượng blob (ví dụ: chữ ký GPG ).
  • các nhánh nằm trong refs/heads/không gian tên và chỉ có thể trỏ đến các đối tượng . Con HEADtrỏ phải tham chiếu đến một nhánh (tham chiếu tượng trưng) hoặc trực tiếp đến một cam kết (tách ra CHÍNH hoặc nhánh không được đặt tên).
  • chi nhánh theo dõi từ xa nằm trong refs/remotes/<remote>/không gian tên và theo dõi các nhánh thông thường trong kho lưu trữ từ xa <remote>.

Xem thêm trang chủ gitglossary :

chi nhánh

Một "nhánh" là một dòng phát triển tích cực. Cam kết gần đây nhất trên một chi nhánh được gọi là tiền boa của chi nhánh đó. Đầu của nhánh được tham chiếu bởi một đầu chi nhánh, di chuyển về phía trước khi phát triển bổ sung được thực hiện trên nhánh. Một kho lưu trữ git duy nhất có thể theo dõi số lượng nhánh tùy ý, nhưng cây làm việc của bạn được liên kết với chỉ một trong số chúng (nhánh "hiện tại" hoặc "đã kiểm tra") và HEAD chỉ vào nhánh đó.

nhãn

Một ref chỉ vào một thẻ hoặc cam kết đối tượng. Ngược lại với một cái đầu, một thẻ không bị thay đổi bởi một cam kết. Thẻ (không phải đối tượng thẻ) được lưu trữ trong $GIT_DIR/refs/tags/. [...]. Một thẻ thường được sử dụng để đánh dấu một điểm cụ thể trong chuỗi tổ tiên cam kết.

đối tượng thẻ

Một đối tượng chứa một tham chiếu trỏ đến một đối tượng khác, có thể chứa một thông điệp giống như một đối tượng cam kết. Nó cũng có thể chứa chữ ký (PGP), trong trường hợp đó được gọi là "đối tượng thẻ đã ký".


36
Câu hỏi: nếu bạn coi một nhánh giống như một thẻ (nghĩa là bạn tạo nó, sau đó không bao giờ cập nhật nó), có sự khác biệt thực sự nào không?
Steve Bennett

30
@SteveBennett hoàn toàn. Có chứa các thông tin khác nhau (bạn có thể ký một thẻ, bạn có thể thêm một mô tả cho một chi nhánh). Bạn có thể di chuyển một nhánh (vì vậy ngay cả khi bạn không bao giờ cập nhật nó, bạn vẫn có thể khởi động lại nó.). Bạn không thể di chuyển một thẻ (nó được liên kết với một cam kết cụ thể). Bạn có thể chọn để đẩy một chi nhánh. Thẻ không được đẩy theo mặc định. Bạn không bao giờ nên sử dụng cái này cho cái kia (trừ khi bạn thực sự có suy nghĩ về SVN, trong trường hợp đó bạn cần "không học" nhanh như vậy nếu bạn muốn tiếp tục với git).
VonC

19
@SteveBennett: Có một sự khác biệt về cách Git đối xử với các nhánh so với cách nó xử lý các thẻ. Bên cạnh những gì VonC đã nói, bạn không thể chuyển thẻ do nhầm lẫn: " git checkout <tag>" sẽ tạo ra nhánh không tên ẩn danh (còn gọi là 'tách rời') và chọn trạng thái của thẻ. Tạo một cam kết mới thực hiện nó trên nhánh không tên này và không thay đổi thẻ nào trỏ đến.
Jakub Narębski

60
IMO, các nhánh là các mốc thời gian riêng biệt (thế giới song song) và thẻ là những khoảnh khắc cụ thể tại dòng thời gian.
Eonil

25
Không ai ở đây đã đề cập đến nó nhưng bạn có thể sử dụng thẻ làm điểm để bắt đầu một chi nhánh:git checkout -b <branch name> <tag name>

143

Nếu bạn nghĩ về kho lưu trữ của bạn như một cuốn sách ghi lại quá trình phát triển dự án của bạn ...

Chi nhánh

Bạn có thể nghĩ về một nhánh là một trong những dấu trang dính đó :

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

Kho lưu trữ hoàn toàn mới chỉ có một trong số đó (được gọi master), tự động chuyển sang trang mới nhất (nghĩ là cam kết ) bạn đã viết. Tuy nhiên, bạn có thể tự do tạo và sử dụng nhiều dấu trang hơn để đánh dấu các điểm ưa thích khác trong sách để bạn có thể nhanh chóng quay lại chúng.

Ngoài ra, bạn luôn có thể di chuyển một dấu trang cụ thể sang một số trang khác của cuốn sách (sử dụng git-reset ví dụ: ); điểm quan tâm thường thay đổi theo thời gian.

Thẻ

Bạn có thể nghĩ về các thẻ như tiêu đề chương .

dấu trang

Nó có thể chứa một tiêu đề (nghĩ các thẻ chú thích ) hoặc không. Một thẻ tương tự nhưng khác với một nhánh, trong đó nó đánh dấu một điểm quan tâm lịch sử trong cuốn sách. Để duy trì khía cạnh lịch sử của nó, một khi bạn đã chia sẻ thẻ (nghĩa là đẩy nó vào một điều khiển từ xa được chia sẻ), bạn không cần phải di chuyển nó đến một nơi khác trong cuốn sách.


16
Tôi sẽ hình dung rằng một nhánh sẽ là một cuốn sách và dấu trang là các thẻ. Bạn có thể tiếp tục viết một cuốn sách, nhưng bạn không thể chỉnh sửa nó. Tag chỉ là một khoảnh khắc cố định trong cuốn sách.
Mārtiņš Briedis

5
@Jubobs Tôi thích giải thích chi nhánh như một dòng phát triển. Một cuốn sách sẽ là một chi nhánh. Bạn có thể bắt đầu một cuốn sách mới dựa trên nơi rời khỏi nhánh chính. Bạn có thể viết chúng song song và sau đó cố gắng hợp nhất vào một cuốn sách / chi nhánh.
Mārtiņš Briedis

2
@ MārtiņšBriedis Tôi hiểu cách bạn muốn nghĩ về một chi nhánh, nhưng tôi thấy rằng, trong Git, điều đó thực sự gây hiểu lầm. Xem stackoverflow.com/questions/25068543/ từ
jub0bs 16/215

2
đây thực sự là một câu trả lời tiết kiệm thời gian
Ali Foroughi

2
Nếu bạn bắt đầu viết một cuốn sách và bạn có 50 trang đầu tiên, bạn có thể sao chép nó (tạo một nhánh mới từ nó) và tiếp tục viết hai cuốn sách cùng lúc (hoặc đưa bản sao sách cho một nhà văn - nhà phát triển khác) và cuối cùng bạn có thể hợp nhất thay đổi từ cuốn sách khác sang cuốn sách của bạn.
barell

42

Điều bạn cần nhận ra, đến từ CVS, là bạn không còn tạo thư mục khi thiết lập chi nhánh.
Không còn "thẻ dính" (có thể được áp dụng cho chỉ một tệp) hoặc "thẻ nhánh".
Nhánh và thẻ là hai đối tượng khác nhau trong Git và chúng luôn áp dụng cho tất cả repo.

Bạn sẽ không còn (với SVN lần này) phải cấu trúc rõ ràng kho lưu trữ của bạn với:

branches
   myFirstBranch
     myProject
       mySubDirs
   mySecondBranch
     ...
tags
   myFirstTag
     myProject
       mySubDirs
   mySecondTag
   ...

Cấu trúc đó xuất phát từ thực tế CVS là một hệ thống sửa đổi chứ không phải hệ thống phiên bản (xem Kiểm soát nguồn so với Kiểm soát sửa đổi? ).
Điều đó có nghĩa là các nhánh được mô phỏng thông qua các thẻ cho CVS, các bản sao thư mục cho SVN.

Câu hỏi của bạn có ý nghĩa nếu bạn được sử dụng để kiểm tra thẻ và bắt đầu làm việc với nó .
Mà bạn không nên;)
Một thẻ được cho là đại diện cho một bất biến nội dung , chỉ được sử dụng để truy cập nó với sự đảm bảo để có được cùng một nội dung mỗi lần.

Trong Git, lịch sử sửa đổi là một loạt các cam kết, tạo thành một biểu đồ.
Một nhánh là một đường dẫn của đồ thị

x--x--x--x--x # one branch
    \ 
     --y----y # another branch
       1.1
        ^
        |
        # a tag pointing to a commit
  • Nếu bạn kiểm tra một thẻ, bạn sẽ cần tạo một nhánh để bắt đầu làm việc từ nó.
  • Nếu bạn kiểm tra một chi nhánh, bạn sẽ trực tiếp thấy cam kết mới nhất ('ĐẦU') của chi nhánh đó.

Xem câu trả lời của Jakub Narębski cho tất cả các kỹ thuật, nhưng thẳng thắn, tại thời điểm này, bạn không cần (chưa) tất cả các chi tiết;)

Điểm chính là: một thẻ là một con trỏ đơn giản cho một cam kết, bạn sẽ không bao giờ có thể sửa đổi nội dung của nó. Bạn cần một chi nhánh.


Trong trường hợp của bạn, mỗi nhà phát triển làm việc trên một tính năng cụ thể:

  • nên tạo chi nhánh riêng của họ trong kho lưu trữ tương ứng của họ
  • theo dõi các chi nhánh từ kho của đồng nghiệp của họ (nhóm hoạt động trên cùng một tính năng)
  • kéo / đẩy để chia sẻ công việc của bạn với các đồng nghiệp của bạn.

Thay vì theo dõi trực tiếp các chi nhánh của đồng nghiệp, bạn chỉ có thể theo dõi chi nhánh của một kho lưu trữ trung tâm "chính thức" mà mọi người đẩy công việc của mình để tích hợp và chia sẻ công việc của mọi người cho tính năng cụ thể này.


1
cảm ơn vì đã làm rõ cách các chi nhánh và thẻ hoạt động :) tôi sẽ không thể hiểu đầy đủ về nó nếu không có ví dụ của bạn.
ufk

3
@VonC: Tôi nghĩ bạn có nghĩa là "SVN" trong câu trả lời của bạn chứ không phải "CVS". CVS không có cấu trúc thư mục; SVN nào. Trên thực tế, việc gắn thẻ trong git nhắc nhở tôi nhiều hơn về việc gắn thẻ trong RCS / CVS so với việc gắn thẻ trong SVN (trong đó tag == nhánh suy biến).
Chris Cleeland

1
@ChrisCleeland điểm tốt. Tôi đã cố gắng tách thêm một chút điểm CVS và SVN trong câu trả lời (đã chỉnh sửa).
VonC

37

Cành được làm bằng gỗ và mọc từ thân cây. Thẻ được làm bằng giấy (dẫn xuất từ ​​gỗ) và treo như đồ trang trí Giáng sinh từ nhiều nơi khác nhau trên cây.

Dự án của bạn là cây và tính năng của bạn sẽ được thêm vào dự án sẽ phát triển trên một nhánh. Câu trả lời là chi nhánh.


3
tình yêu cho sự tương tự
doz87

16

Có vẻ như cách tốt nhất để giải thích là các thẻ hoạt động như các nhánh chỉ đọc. Bạn có thể sử dụng một nhánh làm thẻ, nhưng bạn có thể vô tình cập nhật nó với các cam kết mới. Các thẻ được đảm bảo để trỏ đến cùng một cam kết miễn là chúng tồn tại.


11
Các thẻ được đảm bảo để trỏ đến cùng một cam kết miễn là chúng tồn tại. Không hoàn toàn đúng. Bạn thực sự có thể di chuyển một thẻ với git tag -f.
jub0bs

14

Các thẻ có thể được ký hoặc không dấu ; các chi nhánh không bao giờ được ký kết.

Các thẻ đã ký không bao giờ có thể di chuyển vì chúng được liên kết bằng mật mã (có chữ ký) với một cam kết cụ thể. Thẻ không dấu không bị ràng buộc và có thể di chuyển chúng (nhưng thẻ di chuyển không phải là trường hợp sử dụng thông thường).

Các chi nhánh không chỉ có thể chuyển sang một cam kết khác mà còn được dự kiến ​​sẽ làm như vậy. Bạn nên sử dụng một chi nhánh cho dự án phát triển địa phương của bạn. Sẽ không có ý nghĩa gì khi cam kết công việc với kho Git "trên thẻ".


12

Tôi thích nghĩ về các chi nhánh như nơi bạn sẽ đến , các thẻ như nơi bạn đã đến .

Thẻ cảm thấy giống như một dấu trang của một điểm quan trọng cụ thể trong quá khứ, chẳng hạn như phiên bản phát hành.

Trong khi một chi nhánh là một con đường cụ thể mà dự án đang đi xuống, và do đó, điểm đánh dấu chi nhánh tiến lên với bạn. Khi bạn hoàn thành, bạn hợp nhất / xóa chi nhánh (tức là điểm đánh dấu). Tất nhiên, tại thời điểm đó bạn có thể chọn gắn thẻ cam kết đó.


10

Các Git Dụ ngôn giải thích làm thế nào một DVCS điển hình được tạo ra và tại sao người sáng tạo của họ đã làm những gì họ đã làm. Ngoài ra, bạn có thể muốn xem Git cho Nhà khoa học máy tính ; nó giải thích từng loại đối tượng trong Git, bao gồm các nhánh và thẻ.


6

Thẻ được sử dụng để đánh dấu một phiên bản, cụ thể hơn là nó tham chiếu một điểm trong thời gian trên một nhánh. Một nhánh thường được sử dụng để thêm các tính năng cho một dự án.


4

đơn giản:

Các thẻ được dự kiến ​​sẽ luôn luôn trỏ đến cùng một phiên bản của một dự án, trong khi các đầu được dự kiến ​​sẽ tiến lên khi tiến trình phát triển.

Hướng dẫn sử dụng Git


4

câu trả lời đơn giản là:

nhánh: con trỏ nhánh hiện tại di chuyển với mọi cam kết vào kho lưu trữ

nhưng

thẻ: cam kết mà điểm thẻ không thay đổi, trên thực tế thẻ là ảnh chụp nhanh của cam kế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.