Làm thế nào tôi có thể lưu trữ các chi nhánh git?


305

Tôi có một số nhánh cũ trong kho git của tôi không còn được phát triển. Tôi muốn lưu trữ các nhánh để chúng không hiển thị theo mặc định khi chạy git branch -l -r. Tôi không muốn xóa chúng, vì tôi muốn giữ lại lịch sử. Tôi có thể làm cái này như thế nào?

Tôi biết rằng có thể tạo một ref bên ngoài ref / Heads. Ví dụ , refs/archive/old_branch. Có bất kỳ hậu quả của việc làm đó?


git-rm không xóa tài nguyên khỏi kho lưu trữ, nó chỉ xóa chúng khỏi chỉ mục kernel.org/pub/software/scm/git/docs/git-rm.html Bạn có thể dễ dàng khôi phục các tài nguyên này bằng cách sử dụnggit checkout [rev] file
Dana the Sane

1
Không phải là tôi biết. Tôi sử dụng Attic/<branchname>các thẻ nhẹ để lưu trữ các chi nhánh, mặc dù.
Jakub Narębski

thẻ là sự lựa chọn nhanh chóng và an toàn và lành mạnh.
kch

Câu trả lời:


401

Tôi tin rằng cách thích hợp để làm điều này là gắn thẻ chi nhánh. Nếu bạn xóa chi nhánh sau khi bạn đã gắn thẻ thì bạn đã giữ chi nhánh xung quanh một cách hiệu quả nhưng nó sẽ không làm lộn xộn danh sách chi nhánh của bạn.

Nếu bạn cần quay trở lại chi nhánh, chỉ cần kiểm tra thẻ. Nó sẽ có hiệu quả khôi phục chi nhánh từ thẻ.

Để lưu trữ và xóa chi nhánh:

git tag archive/<branchname> <branchname>
git branch -d <branchname>

Để khôi phục chi nhánh một thời gian sau:

git checkout -b <branchname> archive/<branchname>

Lịch sử của chi nhánh sẽ được lưu giữ chính xác như khi bạn gắn thẻ.


11
Tôi là người mới chơi Git, nhưng khi thử điều này, tôi nghĩ rằng lệnh thích hợp để khôi phục chi nhánh là:git checkout -b <branchname> archive/<branchname>
Steve

6
Có lý do nào để không sử dụng thẻ đối tượng trong trường hợp này không? Có thể xem ai đã lưu trữ chi nhánh và khi nào có thể thú vị.
Grégory Joseph

7
@ GrégoryJoseph: Đó là cái gọi là "thẻ chú thích". Và vâng, sử dụng nó có thể có nhiều ý nghĩa, tôi nói.
onnodb

22
lưu ý nhỏ, bạn có thể muốn branch -Dvì nó có thể không được hợp nhất hoàn toàn nếu bạn lưu trữ nó theo cách này
Arkadiy Kukarkin

5
Rất đẹp. Dưới đây là một hướng dẫn đầy đủ với lời giải thích.
Guyaloni 4/2/2015

123

Câu trả lời của Jeremy là đúng về nguyên tắc, nhưng IMHO các lệnh mà anh ta chỉ định không hoàn toàn đúng.

Dưới đây là cách lưu trữ chi nhánh vào thẻ mà không cần phải kiểm tra chi nhánh (và do đó, không phải kiểm tra chi nhánh khác trước khi bạn có thể xóa chi nhánh đó):

> git tag archive/<branchname> <branchname>
> git branch -D <branchname>

Và đây là cách khôi phục chi nhánh:

> git checkout -b <branchname> archive/<branchname>

18
Tôi đoán bạn chưa có đủ điểm nhưng sẽ tốt hơn khi bạn chỉ cần chỉnh sửa câu trả lời hiện có - dù sao đi nữa :)
jkp

5
@jkp chỉnh sửa mã và lệnh của người dùng khác thường bị cau mày vì những thay đổi tinh tế trong lệnh git có thể làm những việc khác nhau đáng kể và bạn có thể không hiểu tại sao tác giả ban đầu lại viết một cái gì đó theo cách họ đã làm. tốt hơn là chỉ đưa ra câu trả lời của riêng bạn hoặc để lại nhận xét.
Dan Bechard

Hoặc thậm chí tệ hơn những thứ khác biệt mạnh mẽ, một sự thay đổi tinh tế trong các lệnh hoặc mã có thể dẫn đến kết quả khác nhau một cách tinh tế, điều này thực sự khó để tìm ra, tôi sẽ đề nghị để lại như một bình luận để người đăng câu trả lời có thể tự chỉnh sửa hoặc trả lời với một yêu cầu phản tố tham chiếu các kết quả có khả năng khác nhau (Điều mà các yêu cầu phản tố như vậy khá phổ biến)
Nicholas Pipitone

22

Có, bạn có thể tạo một ref với một số tiền tố không chuẩn bằng cách sử dụng git update-ref. ví dụ

  • Lưu trữ chi nhánh: git update-ref refs/archive/old-topic topic && git branch -D topic
  • Khôi phục chi nhánh (nếu cần): git branch topic refs/archive/old-topic

Các tham chiếu có tiền tố không chuẩn (ở đây refs/archive) sẽ không hiển thị trên bình thường git branch, git logcũng không git tag. Tuy nhiên, bạn có thể liệt kê chúng với git for-each-ref.

Tôi đang sử dụng các bí danh sau:

[alias]
    add-archive = "!git update-ref refs/archive/$(date '+%Y%m%d-%s')"
    list-archive = for-each-ref --sort=-authordate --format='%(refname) %(objectname:short) %(contents:subject)' refs/archive/
    rem = !git add-archive
    lsrem = !git list-archive

Ngoài ra, bạn có thể muốn định cấu hình điều khiển từ xa như push = +refs/archive/*:refs/archive/*tự động đẩy các nhánh lưu trữ (hoặc git push origin refs/archive/*:refs/archive/*cho một lần bắn).

Một cách khác là viết ra SHA1 ở đâu đó trước khi xóa chi nhánh, nhưng nó có những hạn chế. Các cam kết không có bất kỳ giới thiệu nào sẽ là GC'd sau 3 tháng (hoặc một vài tuần mà không cần reflog) , hãy để một mình thủ công git gc --prune. Cam kết được chỉ định bởi refs là an toàn từ GC.

Chỉnh sửa: Tìm thấy một triển khai perl của cùng một ý tưởng bởi @ap :git-attic

Chỉnh sửa ^ 2: Tìm thấy một bài đăng trên blog trong đó chính Gitster sử dụng kỹ thuật tương tự.


3
Tuyệt vời, ngoài những người khác về chủ đề này, bạn thực sự đã trả lời câu hỏi.
tzrlk

20

Mở rộng câu trả lời của Steve để phản ánh những thay đổi trên điều khiển từ xa, tôi đã làm

 git tag archive/<branchname> <branchname>
 git branch -D <branchname>
 git branch -d -r origin/<branchname>
 git push --tags
 git push origin :<branchname>

Để khôi phục từ xa, xem câu hỏi này .


18

Bạn có thể lưu trữ các chi nhánh trong kho lưu trữ khác. Không hoàn toàn thanh lịch, nhưng tôi muốn nói đó là một sự thay thế khả thi.

git push git://yourthing.com/myproject-archive-branches.git yourbranch
git branch -d yourbranch

4
Bạn có thể tạo git-bundlethay vì kho lưu trữ riêng biệt.
Jakub Narębski

9

Đây là một bí danh cho điều đó:

arc    = "! f() { git tag archive/$1 $1 && git branch -D $1;}; f"

Thêm nó như thế này:

git config --global alias.arc '! f() { git tag archive/$1 $1 && git branch -D $1;}; f'

Hãy nhớ rằng đã có git archivelệnh để bạn không thể sử dụng archivelàm tên bí danh.

Ngoài ra, bạn có thể xác định bí danh để xem danh sách các nhánh 'được lưu trữ':

arcl   = "! f() { git tag | grep '^archive/';}; f"

về việc thêm bí danh


3
Với các phiên bản mới hơn của git (như được đề xuất ở đây ), bí danh này sẽ hoàn tất:!git tag archive/$1 $1 && git branch -D
Thiếu

5

Tôi đang sử dụng các bí danh sau để ẩn các nhánh lưu trữ:

[alias]
    br = branch --no-merge master # show only branches not merged into master
    bra = branch                  # show all branches

Vì vậy, git brđể hiển thị các nhánh phát triển tích cực và git brahiển thị tất cả các nhánh bao gồm cả các nhánh "được lưu trữ" .


5
Việc một nhánh đã được sáp nhập vào master không liên quan gì đến trạng thái lưu trữ của nó. Ví dụ, trong nhóm nhà phát triển của tôi, chúng tôi có một vài chi nhánh được tạo riêng để kiểm tra công cụ. Chúng tôi muốn giữ các nhánh đó trong kho lưu trữ của chúng tôi, nhưng chúng tôi chắc chắn không muốn hợp nhất chúng thành chủ.
Bart

4

Tôi sẽ không lưu trữ các chi nhánh. Đặt cách khác, chi nhánh tự lưu trữ. Những gì bạn muốn là đảm bảo thông tin liên quan đến các nhà khảo cổ học có thể được tìm thấy bằng các phương tiện đáng tin cậy. Đáng tin cậy ở chỗ họ hỗ trợ phát triển hàng ngày và không thêm một bước nữa vào quá trình hoàn thành công việc. Đó là, tôi không tin mọi người sẽ nhớ thêm một thẻ khi chúng được thực hiện với một nhánh.

Đây là hai bước đơn giản sẽ giúp ích rất nhiều cho khảo cổ học phát triển.

  1. Liên kết mỗi nhánh nhiệm vụ với một vấn đề liên quan trong trình theo dõi vấn đề bằng cách sử dụng quy ước đặt tên đơn giản .
  2. Luôn luôn sử dụng git merge --no-ffđể hợp nhất các nhánh nhiệm vụ; bạn muốn hợp nhất cam kết và bong bóng lịch sử, thậm chí chỉ cho một cam kết.

Đó là nó. Tại sao? Bởi vì là một nhà khảo cổ học mã, hiếm khi tôi bắt đầu muốn biết những gì công việc đã được thực hiện trên một nhánh. Thường xuyên hơn đó là lý do tại sao trong tất cả chín địa ngục đang la hét là mã được viết theo cách này?! Tôi cần thay đổi mã, nhưng nó có một số tính năng kỳ lạ, và tôi cần giải mã chúng để tránh phá vỡ thứ gì đó quan trọng.

Bước tiếp theo là git blametìm các cam kết liên quan và sau đó hy vọng thông điệp tường trình là giải thích. Nếu tôi cần đào sâu hơn, tôi sẽ tìm hiểu xem công việc đã được thực hiện trong một chi nhánh và đọc toàn bộ chi nhánh chưa (cùng với lời bình luận của nó trong trình theo dõi vấn đề).

Hãy nói git blameđiểm tại cam kết XYZ. Tôi mở trình duyệt lịch sử Git (gitk, GitX git log --decorate --graph, v.v.), tìm cam kết XYZ và xem ...

AA - BB - CC - DD - EE - FF - GG - II ...
     \                       /
      QQ - UU - XYZ - JJ - MM

Có chi nhánh của tôi! Tôi biết QQ, UU, XYZ, JJ và MM đều là một phần của cùng một chi nhánh và tôi nên xem thông điệp tường trình của họ để biết chi tiết. Tôi biết GG sẽ là một cam kết hợp nhất và có tên của chi nhánh, hy vọng có liên quan đến một vấn đề trong trình theo dõi.

Nếu, vì một số lý do, tôi muốn tìm một nhánh cũ tôi có thể chạy git logvà tìm kiếm tên nhánh trong cam kết hợp nhất. Nó đủ nhanh ngay cả trên các kho rất lớn.

Đó là những gì tôi muốn nói khi tôi nói rằng các chi nhánh lưu trữ chính họ.

Gắn thẻ cho mọi chi nhánh sẽ thêm công việc không cần thiết để hoàn thành công việc (một quy trình quan trọng cần được sắp xếp một cách tàn nhẫn), tổng hợp danh sách thẻ (không nói về hiệu suất, nhưng khả năng đọc của con người) với hàng trăm thẻ chỉ thỉnh thoảng rất hữu ích và không phải là ' t thậm chí rất hữu ích cho khảo cổ học.


2
Nhưng những gì về sự lộn xộn? Có lẽ nếu có một cách để che giấu những cành cây cũ dưới 10 mét khối đất.
bvj

1
Điều này rất hữu ích, nhưng nó không áp dụng cho các chi nhánh không được hợp nhất. Đôi khi một thử nghiệm đã được thực hiện trên một nhánh và bạn muốn giữ nội dung trong trường hợp một số nội dung đó trở nên hữu ích sau này.
Neil Mayhew

1
@bvj Tôi nghĩ rằng câu trả lời này gợi ý bạn nên luôn luôn xóa các nhánh được hợp nhất, bởi vì bạn luôn có thể quay lại với chúng thông qua cam kết hợp nhất. Tôi đồng ý với điều này.
Neil Mayhew

@NeilMayhew Vâng, tôi có khoảng 10 chi nhánh không hợp nhất như thế tự mở. Mỗi cái được liên kết với một nhiệm vụ mở để tôi có thể nhớ những gì tôi đã làm. Tôi sẽ làm gì đó với họ, hoặc họ trở nên lỗi thời, họ không còn phù hợp nữa và tôi sẽ xóa chúng. Tôi đã làm việc trong một dự án hoàn toàn chìm đắm trong các nhánh "Tôi có thể cần nó sau này" vì vậy chúng tôi khó có thể thấy những gì chúng tôi đang làm. Đó thực sự là một cái cớ để một số nhà phát triển không phải tự dọn dẹp. Một chút chậm trễ là tốt, nhưng đừng để nó vượt khỏi tầm kiểm soát.
Schwern 30/03/19

@Schwern tôi đồng ý. Tôi cũng đã từng tham gia những dự án như thế. Tôi nghĩ rằng chuyển đổi các nhánh thành thẻ là một cách tốt để thoát khỏi sự lộn xộn, bởi vì danh sách các thẻ sẽ luôn phát triển trong khi danh sách các nhánh không nên (vì nó đại diện cho số lượng công việc đang diễn ra). Sử dụng không gian tên cho các thẻ làm cho danh sách dễ quản lý hơn, nhưng xu hướng packrat chắc chắn cần phải được chống lại. Một nhà phát triển nên giữ lại các cam kết trên máy của họ trừ khi có cơ hội tốt để người khác cuối cùng sẽ sử dụng chúng.
Neil Mayhew

2

Cách tiếp cận của tôi là đổi tên tất cả các chi nhánh mà tôi không quan tâm bằng tiền tố "thùng rác", sau đó sử dụng:

git branch | grep -v trash

(với một ràng buộc khóa vỏ)

Để giữ lại màu của nhánh hoạt động, người ta sẽ cần:

git branch --color=always | grep --color=never --invert-match trash

2
Nếu đổi tên các nhánh, bạn cũng có thể đặt chúng vào một không gian tên "archive /"
qneill

1

Bạn có thể sử dụng một tập lệnh sẽ lưu trữ chi nhánh cho bạn

tổng tài

Nó tạo ra một thẻ cho bạn với kho lưu trữ tiền tố / và sau đó xóa chi nhánh. Nhưng kiểm tra mã trước khi bạn sử dụng nó.


Sử dụng - $/your/location/of/script/archbranch [branchname] [defaultbranch]

Nếu bạn muốn chạy tập lệnh mà không viết vị trí cho nó, hãy thêm nó vào đường dẫn của bạn

Sau đó, bạn có thể gọi nó bằng

$ archbranch [branchname] [defaultbranch]

Đây [defaultbranch]là nhánh mà nó sẽ đi đến khi việc lưu trữ được thực hiện. Có một số vấn đề với mã màu nhưng khác là nó sẽ hoạt động. Tôi đã sử dụng nó trong các dự án trong một thời gian dài, nhưng nó vẫn đang được phát triển.


1
Mỗi ngăn xếp tràn trợ giúp , bạn cần tiết lộ liên kết của bạn với sản phẩm của bạn.
LittleBulkTables - Au Revoir

Ồ, xin lỗi, không biết. Tôi là tác giả của kịch bản.
Banezaka

0

Đôi khi tôi lưu trữ các nhánh như sau:

  1. Tạo các tệp vá, ví dụ: format-patch <branchName> <firstHash>^..<lastHash>(sử dụng FirstHash và lastHash bằng cách sử dụng git log <branchName>.
  2. Di chuyển các tệp vá được tạo vào thư mục trên một máy chủ tệp.
  3. Xóa chi nhánh, ví dụ: git branch -D <branchName>

"Áp dụng" bản vá khi bạn cần sử dụng lại chi nhánh; tuy nhiên, việc áp dụng các tệp vá (xem git am) có thể khó khăn tùy thuộc vào trạng thái của nhánh đích. Về mặt tích cực, phương pháp này có lợi ích là cho phép các cam kết của chi nhánh được thu gom rác và tiết kiệm không gian trong kho của bạn.

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.