Những gì bạn muốn làm là rất phá vỡ nếu bạn đã xuất bản lịch sử cho các nhà phát triển khác. Xem Phục hồi từ thượng nguồn Rebase Hồi giáo trong git rebase
tài liệu cho các bước cần thiết sau khi sửa chữa lịch sử của bạn.
Bạn có ít nhất hai tùy chọn: git filter-branch
và một rebase tương tác, cả hai đều được giải thích bên dưới.
Sử dụng git filter-branch
Tôi gặp vấn đề tương tự với dữ liệu kiểm tra nhị phân cồng kềnh từ nhập Subversion và đã viết về việc xóa dữ liệu khỏi kho git .
Nói lịch sử git của bạn là:
$ git lola --name-status
* f772d66 (HEAD, master) Login page
| A login.html
* cb14efd Remove DVD-rip
| D oops.iso
* ce36c98 Careless
| A oops.iso
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Lưu ý rằng git lola
là một bí danh không chuẩn nhưng rất hữu ích. Với công --name-status
tắc, chúng ta có thể thấy các sửa đổi cây liên quan đến từng cam kết.
Trong cam kết của Carless, (có tên đối tượng SHA1 là ce36c98), tệp oops.iso
này là DVD-rip được thêm vào một cách tình cờ và bị xóa trong lần xác nhận tiếp theo, cb14efd. Sử dụng kỹ thuật được mô tả trong bài viết trên blog đã nói ở trên, lệnh để thực thi là:
git filter-branch --prune-empty -d /dev/shm/scratch \
--index-filter "git rm --cached -f --ignore-unmatch oops.iso" \
--tag-name-filter cat -- --all
Tùy chọn:
--prune-empty
loại bỏ các xác nhận trở nên trống rỗng ( nghĩa là không thay đổi cây) do hoạt động của bộ lọc. Trong trường hợp điển hình, tùy chọn này tạo ra một lịch sử sạch hơn.
-d
đặt tên một thư mục tạm thời chưa tồn tại để sử dụng để xây dựng lịch sử đã lọc. Nếu bạn đang chạy trên một bản phân phối Linux hiện đại, chỉ định một cây trong/dev/shm
sẽ dẫn đến việc thực thi nhanh hơn .
--index-filter
là sự kiện chính và chạy ngược lại chỉ số ở mỗi bước trong lịch sử. Bạn muốn xóa oops.iso
bất cứ nơi nào nó được tìm thấy, nhưng nó không có trong tất cả các cam kết. Lệnhgit rm --cached -f --ignore-unmatch oops.iso
xóa DVD-rip khi có mặt và không bị lỗi khác.
--tag-name-filter
mô tả cách viết lại tên thẻ. Một bộ lọc củacat
là hoạt động nhận dạng. Kho lưu trữ của bạn, như mẫu ở trên, có thể không có bất kỳ thẻ nào, nhưng tôi đã bao gồm tùy chọn này để có tính tổng quát.
--
chỉ định kết thúc các tùy chọn để git filter-branch
--all
tiếp theo --
là tốc ký cho tất cả các ref. Kho lưu trữ của bạn, giống như mẫu ở trên, có thể chỉ có một ref (chính), nhưng tôi đã bao gồm tùy chọn này để có tính tổng quát.
Sau một vài lần khuấy động, lịch sử bây giờ là:
$ git lola --name-status
* 8e0a11c (HEAD, master) Login page
| A login.html
* e45ac59 Careless
| A other.html
|
| * f772d66 (refs/original/refs/heads/master) Login page
| | A login.html
| * cb14efd Remove DVD-rip
| | D oops.iso
| * ce36c98 Careless
|/ A oops.iso
| A other.html
|
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Lưu ý rằng cam kết mới của Car Carless chỉ bổ sung other.html
và cam kết xóa Xóa DVD DVD không còn trên nhánh chính. Chi nhánh được dán nhãn refs/original/refs/heads/master
chứa các cam kết ban đầu của bạn trong trường hợp bạn mắc lỗi. Để xóa nó, hãy làm theo các bước trong Danh sách kiểm tra để thu nhỏ kho lưu trữ.
$ git update-ref -d refs/original/refs/heads/master
$ git reflog expire --expire=now --all
$ git gc --prune=now
Để thay thế đơn giản hơn, sao chép kho lưu trữ để loại bỏ các bit không mong muốn.
$ cd ~/src
$ mv repo repo.old
$ git clone file:///home/user/src/repo.old repo
Sử dụng một file:///...
bản sao URL sao chép các đối tượng thay vì chỉ tạo các liên kết cứng.
Bây giờ lịch sử của bạn là:
$ git lola --name-status
* 8e0a11c (HEAD, master) Login page
| A login.html
* e45ac59 Careless
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
Tên đối tượng SHA1 cho hai lần xác nhận đầu tiên (trang Index Index và trang quản trị trang trực tuyến) giữ nguyên vì hoạt động của bộ lọc không sửa đổi các cam kết đó. oops.iso
Trang web không có người lái bị mất và người đăng nhập Trang đã có một phụ huynh mới, vì vậy SHA1 của họ đã thay đổi.
Rebase tương tác
Với lịch sử:
$ git lola --name-status
* f772d66 (HEAD, master) Login page
| A login.html
* cb14efd Remove DVD-rip
| D oops.iso
* ce36c98 Careless
| A oops.iso
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
bạn muốn loại bỏ oops.iso
khỏi dịch vụ của Car Carless như thể bạn chưa bao giờ thêm nó, và sau đó, Xóa Xóa DVD-rip, là vô dụng đối với bạn. Do đó, kế hoạch của chúng tôi trong một cuộc nổi loạn tương tác là giữ cho trang Admin Admin, chỉnh sửa trực tuyến, không cần chỉnh sửa, xóa và xóa bỏ DVD-rip.
Chạy $ git rebase -i 5af4522
bắt đầu một trình soạn thảo với các nội dung sau.
pick ce36c98 Careless
pick cb14efd Remove DVD-rip
pick f772d66 Login page
# Rebase 5af4522..f772d66 onto 5af4522
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
Thực hiện kế hoạch của chúng tôi, chúng tôi sửa đổi nó thành
edit ce36c98 Careless
pick f772d66 Login page
# Rebase 5af4522..f772d66 onto 5af4522
# ...
Đó là, chúng tôi xóa dòng này bằng cách loại bỏ DVD-rip-Thay đổi và thay đổi hoạt động trên trang web của Car Carless edit
thay vì pick
.
Lưu-thoát trình soạn thảo thả chúng tôi tại một dấu nhắc lệnh với thông báo sau.
Stopped at ce36c98... Careless
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
Như thông báo cho chúng tôi biết, chúng tôi đang thực hiện cam kết của chúng tôi muốn chỉnh sửa, vì vậy chúng tôi chạy hai lệnh.
$ git rm --cached oops.iso
$ git commit --amend -C HEAD
$ git rebase --continue
Việc đầu tiên loại bỏ các tập tin vi phạm từ chỉ mục. Cái thứ hai sửa đổi hoặc sửa đổi Dịch vụ chăm sóc người khuyết tật là một chỉ mục được cập nhật và -C HEAD
hướng dẫn git sử dụng lại thông điệp cam kết cũ. Cuối cùng,git rebase --continue
đi trước với phần còn lại của hoạt động rebase.
Điều này cho một lịch sử của:
$ git lola --name-status
* 93174be (HEAD, master) Login page
| A login.html
* a570198 Careless
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
đó là những gì bạn muốn