2012-06-30 34 views
10

Tôi cần một cam kết không còn trong cơ sở dữ liệu git của các cam kết. Tôi cần phải có khả năng loại bỏ cam kết abc123...git checkout abc123... lợi nhuận error: pathspec 'abc123...' did not match any file(s) known to git.Hoàn toàn xóa cam kết khỏi cơ sở dữ liệu git

Các QA How to delete a 'git commit' câu trả lời này một phần, như trong làm thế nào để loại bỏ các tham chiếu tới một cam kết từ các HEAD, nhưng nó không bao gồm việc tìm kiếm tất cả các chi nhánh một cam kết có mặt trong và cũng không bao gồm hết hạn và thanh trừng cam kết khi nó đã được thực hiện một cam kết lơ lửng.

Làm cách nào để đạt được điều này?

+0

Điều gì đã được thực hiện trong cam kết? Bạn có muốn điều đó vẫn xảy ra, nhưng trong cam kết sau đây? Hoặc đã làm nó, ví dụ: thêm tệp bạn muốn xóa hoàn toàn? Dù bằng cách nào, bạn sẽ phải sử dụng một số hình thức viết lại lịch sử. –

+0

Tôi tìm thấy [bài đăng hữu ích này] (https://wincent.com/wiki/Obliterating_a_Git_commit) bằng cách tìm kiếm trên web cho "git obliterate". –

Trả lời

10
  1. Liệt kê tất cả các chi nhánh có chứa các cam kết:

    git branch --contains COMMITSHA 
    
  2. Remove cam kết từ các chi nhánh:

    git checkout BRANCH 
    git rebase -i COMMITSHA^ 
    # delete line with commit and save 
    

    Nếu một chi nhánh thay đổi được theo dõi trong bất kỳ từ xa, đẩy nó ở đó với ghi đè:

    git push --force REMOTE BRANCH 
    

    ví dụ:

    git push --force origin master 
    

    (Lưu ý rằng, tùy thuộc vào quá trình phát triển của mình, các cam kết có thể xuất hiện tại các chi nhánh từ xa untracked là tốt.)

  3. Purge cam kết, vì vậy nó không thể được khôi phục từ địa phương của bạn repo:

    git reflog expire --all BRANCH1 BRANCH2 # list all branches you changed 
    git prune --expire now 
    

    Lưu ý rằng bạn cũng phải chạy lệnh này trên tất cả kho lưu trữ từ xa có cam kết này. Nếu bạn không có quyền truy cập vào repo từ xa, bạn phải vượt qua các ngón tay của bạn - cam kết cuối cùng sẽ hết hạn của chính nó và sẽ bị thanh trừng bởi git gc.

    Được cảnh báo rằng các lệnh trên sẽ xóa tất cả đối tượng lơ lửng từ Git repo và tất cả lịch sử thay đổi chi nhánh - vì vậy bạn sẽ không thể khôi phục (bằng phương tiện không theo pháp luật) bất cứ thứ gì bị mất trước khi chạy.

  4. Yêu cầu tất cả cộng tác viên tìm nạp các nhánh đã thay đổi và cập nhật bất kỳ công việc nào họ có thể dựa trên chúng.Họ nên làm như sau:

    git fetch REMOTE  
    

    Đối với mỗi chi nhánh đó là dựa trên một chi nhánh bạn đã thay đổi trên (bao gồm cả chi nhánh riêng của mình nếu họ có nó tại địa phương):

    git checkout BRANCH 
    git rebase REMOTE/BRANCH 
    git reflog expire --all BRANCH 
    

    Sau khi họ đang thực hiện:

    git prune --expire now 
    
+0

Điều này sẽ không thực sự loại bỏ đối tượng cam kết đang được đề cập nếu kho lưu trữ đã được kích hoạt lại. – Amber

+0

[Điều này] (https://wincent.com/wiki/Obliterating_a_Git_commit) bao gồm loại bỏ các reflogs là tốt. –

+0

Thêm dọn dẹp không hướng dẫn sử dụng vào câu trả lời (chưa thử nó ...) –

2
  1. Hãy chắc chắn rằng không có refs cần có hành (reset lại trước đó, hoặc rebase nó ra)
  2. Xóa đối tượng từ .git/objects (nó sẽ ở trong một thư mục có tên sau khi hai nhân vật đầu tiên của băm và tên tệp sẽ là phần còn lại của băm).

Lưu ý, tuy nhiên, nếu bạn đẩy cam kết này vào kho lưu trữ công khai, xóa cục bộ sẽ không xóa nó khỏi điều khiển từ xa.

+0

Ouch. Nó có lẽ không phải là một ý tưởng tốt để chạm vào '.git/objects' theo cách thủ công - cho rằng có lệnh' git prune' cho trường hợp này. –

+0

@AlexanderGladysh 'git prune' liên quan đến các bước khác để đảm bảo rằng đối tượng thực sự bị xóa (chẳng hạn như đảm bảo xóa sạch các chỉnh sửa, v.v.). Loại bỏ các tập tin đối tượng trực tiếp không yêu cầu những bước và nói chung là an toàn miễn là bạn không phụ thuộc vào cam kết cho bất cứ điều gì. – Amber

+0

'git reflog hết hạn - tất cả BRANCH' nên làm điều đó, phải không? –

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