2010-04-10 31 views
130

Đến từ svn, chỉ mới bắt đầu làm quen với git.Việc xóa một nhánh trong git có xóa nó khỏi lịch sử không?

Khi nhánh bị xóa trong git, nó có bị xóa khỏi lịch sử không?

Trong svn, bạn có thể dễ dàng khôi phục chi nhánh bằng cách hoàn nguyên thao tác xóa (hợp nhất ngược lại). Giống như tất cả các xóa trong svn, nhánh không bao giờ thực sự bị xóa, nó chỉ bị loại bỏ khỏi cây hiện tại.

Nếu nhánh thực sự bị xóa khỏi lịch sử trong git, điều gì sẽ xảy ra với các thay đổi đã được hợp nhất từ ​​nhánh đó? Chúng được giữ lại?

Trả lời

176

Chi nhánh chỉ là con trỏ để cam kết trong git. Trong git mỗi commit có một cây nguồn hoàn chỉnh, nó là một cấu trúc rất khác với svn, nơi tất cả các nhánh và thẻ (theo quy ước) sống trong 'thư mục' riêng biệt của kho lưu trữ cùng với 'thân cây' đặc biệt.

Nếu chi nhánh được sáp nhập vào một chi nhánh khác trước khi nó bị xóa thì tất cả các cam kết sẽ vẫn có thể truy cập được từ chi nhánh khác khi nhánh đầu tiên bị xóa. Họ vẫn chính xác như họ.

Nếu chi nhánh bị xóa mà không bị sáp nhập vào một chi nhánh khác thì các cam kết trong nhánh đó (cho đến khi điểm được chia tách khỏi cam kết vẫn có thể truy cập được) sẽ ngừng hiển thị.

Các cam kết sẽ vẫn được giữ lại trong kho và có thể khôi phục chúng ngay lập tức sau khi xóa, nhưng cuối cùng chúng sẽ bị thu gom rác.

+2

Cảm ơn câu trả lời. Bạn có thể làm rõ những gì bạn có nghĩa là "mỗi cam kết có một cây nguồn hoàn chỉnh"? Như tôi đã hiểu, mỗi cam kết trong git là một tập hợp các vùng đồng bằng tham chiếu đến một commit cha, chứ không phải toàn bộ cây. –

+0

Không, mỗi cam kết là trạng thái của cây tại một điểm nhất định. Các vùng đồng bằng chỉ được tính sau này để hiển thị và rebasing và whatnot, nhưng các cam kết id là băm của toàn bộ cây. – ben

+1

@Ken Liu: Một cam kết chứa các con trỏ tới số không hoặc nhiều commit cha, một đối tượng cây và một số siêu dữ liệu về cam kết. Do đó, cam kết xác định duy nhất cả hai cây nguồn và, khi được xem với (các) cha mẹ của nó, những thay đổi mà nó đã giới thiệu. –

62

Trong Git, các nhánh chỉ là con trỏ (tham chiếu) để cam kết trong một biểu đồ tuần hoàn theo hướng (DAG) của các cam kết. Điều này có nghĩa là việc xóa một nhánh chỉ loại bỏ các tham chiếu đến các cam kết, mà có thể làm cho một số cam kết trong DAG không thể truy cập, do đó vô hình. Nhưng tất cả các cam kết trên một nhánh bị xóa sẽ vẫn nằm trong kho lưu trữ, ít nhất là cho đến khi các cam kết không thể truy cập được cắt bớt (ví dụ: sử dụng git gc).

Lưu ý rằng git branch -d sẽ từ chối xóa chi nhánh nếu không thể chắc chắn rằng việc xóa nó sẽ không để lại các cam kết không thể truy cập được. Bạn cần phải sử dụng mạnh mẽ hơn git branch -D để buộc xóa chi nhánh nếu nó có thể để lại các cam kết không thể truy cập được. Lưu ý rằng các cam kết không thể truy cập, nếu chúng có mặt, chỉ là những cam kết giữa mũi cuối cùng của nhánh bị xóa và cam kết được sáp nhập với một nhánh khác hiện có, bất kỳ cam kết được gắn thẻ nào hoặc điểm phân nhánh; Bất cứ cái nào đến sau. Ví dụ: trong trường hợp sau:

 
----O----*----*----/M----* <-- master <-- HEAD 
    \   /
     \--.----.--/--x---y  <-- deleted branch 

chỉ cam kết 'x' và 'y' sẽ không thể truy cập được sau khi xóa chi nhánh.

Nếu bạn hoạt động trên một nhánh bị xóa trong thời hạn gc.reflogExpire, mặc định 90 ngày, bạn sẽ có lời khuyên cuối cùng của một chi nhánh xóa ghi trong TRỤ reflog (xem git reflog show HEAD, hoặc git log --oneline --walk-reflogs HEAD). Bạn sẽ có thể sử dụng HEAD reflog để phục hồi con trỏ đã xóa. Cũng lưu ý rằng trong trường hợp này, các cam kết không thể truy cập trong một chi nhánh đã xóa sẽ được bảo vệ khỏi việc cắt xén (xoá) trong khoảng thời gian gc.reflogExpireUnreachable, theo mặc định là 30 ngày.

Nếu bạn không thể tìm thấy đỉnh của một chi nhánh chỉ xóa trong reflog cho HEAD, bạn có thể thử sử dụng git fsck để tìm "unreachable cam <sha1>", và kiểm tra những người (qua git show <sha1> hoặc git log <sha1>) để tìm đầu của nhánh bị xóa.

độc lập về cách bạn tìm thấy những đỉnh của một chi nhánh xóa, bạn có thể hoàn tác xóa, hay đúng hơn là tái tạo một chi nhánh chỉ cần xóa bằng

git branch <deleted-branch> <found-sha1-id> 

Lưu ý tuy nhiên đó reflog cho một chi nhánh sẽ bị mất.


Ngoài ra còn có git-resurrect.sh kịch bản trong contrib/ giúp tìm dấu vết của một mẹo chi nhánh với tên nhất định và hồi sinh (phục hồi) nó.

+0

Tuyệt vời! 'git reflog show HEAD' đã liệt kê cam kết và tôi đã tạo một nhánh mới giống như bạn đã nói, hoàn hảo. –

1

Nếu bạn lo lắng về các chi nhánh vô tình bị xóa và không có bản sao cục bộ của repo nữa, có phần mở rộng cho các máy chủ Git của doanh nghiệp như Gerrit sẽ phát hiện ghi đè lịch sử và xóa chi nhánh, sẽ sao lưu chúng ref để chúng có thể được phục hồi nếu cần thiết và sẽ không bị cắt xén bằng cách thu gom rác thải. Quản trị viên Gerrit vẫn có thể xóa các cam kết đã chọn nếu cần vì lý do pháp lý.

Các vấn đề liên quan