Làm thế nào để thay đổi cam kết trước đây để bao gồm một tệp bị bỏ lỡ?


98

Tôi đã thực hiện một thay đổi và quên thêm tệp vào nhóm thay đổi. Sau các lần cam kết khác, tôi nhận ra tệp hiện bị thiếu trong một lần HEAD^4cam kết.

Làm cách nào để viết lại cam kết trước đó để bao gồm tệp bị thiếu?


bạn đã đẩy 4 cam kết này?
mvp

@mvp nope, chúng chỉ có trên kho lưu trữ git cục bộ của tôi.
kolrie

Câu trả lời:


53

Sử dụng git rebase --interactive HEAD~4và đặt edittùy chọn cho cam kết bạn muốn sửa đổi.

Hãy nhớ rằng bạn không nên sửa đổi các cam kết được đẩy đến kho lưu trữ từ xa theo cách này. Tốt hơn là thêm một cam kết mới với tệp bị thiếu trong trường hợp đó.


Cảm ơn. Đó có phải là trường hợp ngay cả khi tôi là người dùng duy nhất của repo từ xa? Nó sẽ không cho phép tôi làm git push -fnếu tôi chắc chắn rằng ngược dòng không thay đổi?
kolrie

1
Nếu bạn là người dùng duy nhất của repo từ xa, bạn có thể thực hiện động tác ép buộc.
Rafał Rawicki

7
Tôi nghĩ rằng những hướng dẫn này không đủ chi tiết. Khi thử nó lần đầu tiên, tôi nhận được thông báo "Không thể rebase: Chỉ mục của bạn chứa các thay đổi chưa được cam kết." Tôi đã add-ed các tệp bị thiếu, vì vậy tôi đã thực hiện một cam kết với thông báo là "xxx". Sau đó, tôi đã thực hiện lệnh rebase và thay đổi cam kết "xxx" từ "pick" thành "edit". Sau đó, tôi đã làm "git rebase --continue". Bây giờ khi tôi xem lại lịch sử, tôi có "xxx" là cam kết mới nhất và cam kết trước đó tôi muốn thêm chúng vào không thay đổi! Tôi tự hỏi lỗi của tôi là ở đâu?
Darren Cook

2
Việc xóa cam kết cuối cùng sẽ không đưa tệp vào HEAD ~ 4.
Justin

1
git thêm các tập tin đã chỉnh sửa; git cam kết -m "Blah"; git rebase -i HEAD ~ 5; // vì hiện tại đã thêm commit mới nên chúng ta cần phải rebase với 5 thay vì 4. bây giờ hãy di chuyển commit "Blah" sang dòng thứ hai và thay đổi nó từ "Pick" thành "s" (bí) sẽ làm giảm cam kết bằng HEAD ~ 5 như lệnh được thực hiện từ trên xuống dưới
zstring

274

Tôi nhận ra rằng mọi người có thể google và đến đây để tìm một câu trả lời đơn giản hơn: Nếu đó chỉ là lần cam kết cuối cùng thì sao? (Câu hỏi của OP là sửa lỗi cam kết thứ 4 trong lịch sử)

Trong trường hợp bạn cam kết và nhận ra rằng bạn quên thêm một số tệp ngay lập tức , chỉ cần làm:

# edited file-that-i-remember.txt
git add file-that-i-remember.txt
git commit

# realize you forgot a file
git add file-that-i-forgot.txt
git commit --amend --no-edit

Nơi --no-editsẽ giữ cùng một thông điệp cam kết.

Dễ như ăn bánh!


21
Đây là câu trả lời.
Adam Bittlingmayer

5
Đáng nói hơn, nếu các cam kết không được đẩy đến điều khiển từ xa.
Ram Patra

1
Vâng, điều đáng nói ở đây là: Nó là để sử dụng trước khi push . Cảm ơn vì đã chỉ ra điều đó.
Dr Beco

2
Một thông báo là các cam kết trước và sau khi --amendbăm khác nhau
sonlexqt

5
Cảm ơn, nhưng không được: OP đã yêu cầu HEAD^4. Nó ổn theo cách của nó, chỉ như một phụ lục để tham khảo. ;)
Dr Beco

11

Nếu bạn CHƯA đẩy 4 cam kết này, bạn có thể thực hiện như sau:

Tạo tệp vá cho tất cả các cam kết này:

git format-patch -4

Tua lại bằng 4 lần cam kết:

git reset --hard HEAD~4

Thêm tệp bị thiếu:

git add missing-file

Cam kết nó với --amend:

git commit --amend

Áp dụng lại tất cả các bản vá đã lưu:

git am *.patch

Nếu bạn đã đẩy, bạn KHÔNG nên sử dụng phương pháp này. Thay vào đó, chỉ cần thừa nhận sai lầm của bạn và tạo thêm một cam kết trên HEAD để khắc phục sự cố này.


Nếu bạn muốn làm điều này từng bước, việc chọn các cam kết sau khi sửa đổi sẽ dễ dàng hơn là xuất chúng dưới dạng bản vá.
Rafał Rawicki

1
Đây là vấn đề của hương vị. Tôi thích git format-patch/ git amtốt hơn nhiều. Quan trọng nhất là nó mang lại cho bạn sự tự tin hơn nếu bạn làm hỏng điều gì đó - cam kết được lưu dưới dạng bản vá trong tệp vật lý là mạng lưới an toàn tốt nhất của bạn.
mvp

Sự tự tin thực sự nằm trên thực tế, rằng khi hoạt động trên kho lưu trữ git, bạn không bao giờ xóa một thứ. Cam kết cũ có sẵn cho đến khi bạn chạy git gc:)
Rafał Rawicki

Điều này là tầm thường và hiển nhiên đối với bạn và tôi. Tuy nhiên, đối với người dùng mới bắt đầu và có thể không hiểu gì về git - sự thật này không rõ ràng chút nào.
mvp

2
Những hướng dẫn này có vẻ dài dòng, nhưng khá đơn giản và dễ làm theo. Cảm ơn. (Tôi chỉ muốn thêm một bước cuối cùng rm *.patch:)
Darren Cook

9

Mặc dù câu trả lời được chấp nhận là đúng, nhưng nó thiếu hướng dẫn chi tiết về cách thực hiện chỉnh sửa cam kết trong quá trình rebase.

  • Đầu tiên, hãy bắt đầu quá trình rebase:

    git rebase --interactive HEAD~4
    
  • Một danh sách các cam kết sẽ được hiển thị, hãy chọn một cam kết bạn muốn chỉnh sửa bằng cách thay đổi từ pickthành editvà lưu tệp.

  • Thực hiện các sửa đổi cần thiết trong mã của bạn (nhớ gọi git addcác tệp mới)

  • Sau khi tất cả các sửa đổi được thực hiện, hãy phát hành git commit --amend- điều này sẽ sửa đổi một cam kết được đánh dấu làedit

  • Gọi git rebase --continuesẽ kết thúc quá trình (nếu có nhiều cam kết được đánh dấu là edit, các bước trên cần được lặp lại)

Lưu ý quan trọng:

  • KHÔNG xóa các dòng được đánh dấu là pickbạn không muốn chỉnh sửa - hãy để nguyên. Xóa những dòng này sẽ dẫn đến việc xóa các cam kết liên quan

  • GIT buộc bạn phải thực hiện stashtrước khi khôi phục nếu thư mục làm việc của bạn không sạch; Tuy nhiên, bạn có thể git stash pop / git stash applytrong quá trình rebase, để sửa đổi những thay đổi này (tức là những thay đổi được lưu trữ trước khi bắt đầu quá trình rebase) thành một cam kết được đánh dấu làedit

  • nếu có điều gì đó xảy ra và bạn muốn hoàn nguyên các thay đổi được thực hiện trong quá trình rebase trước khi quá trình kết thúc (tức là bạn muốn hoàn nguyên về điểm trước khi bắt đầu rebase), hãy sử dụng git rebase --abort- cũng đọc: Cách hủy bỏ một rebase tương tác nếu --abort doesn ' t làm việc?

  • Như đã nói trong câu trả lời được chấp nhận:

    Hãy nhớ rằng bạn không nên sửa đổi các cam kết được đẩy đến kho lưu trữ từ xa theo cách này. Tốt hơn là thêm một cam kết mới với tệp bị thiếu trong trường hợp đó.

    Câu trả lời tại sao, có trong Sách Git (đoạn có tựa đề " Mối nguy hiểm của sự phục hồi "):

    Không rebase các cam kết tồn tại bên ngoài kho lưu trữ của bạn.

    Nếu bạn làm theo hướng dẫn đó, bạn sẽ ổn thôi. Nếu bạn không làm vậy, mọi người sẽ ghét bạn, và bạn sẽ bị bạn bè và gia đình khinh thường.

    Khi bạn căn cứ lại nội dung, bạn đang bỏ qua các cam kết hiện có và tạo các cam kết mới tương tự nhưng khác biệt. Nếu bạn đẩy các cam kết đến một nơi nào đó và những người khác kéo chúng xuống và dựa trên chúng, sau đó bạn viết lại các cam kết đó bằng git rebase và đẩy chúng lên một lần nữa, cộng tác viên của bạn sẽ phải hợp nhất lại công việc của họ và mọi thứ sẽ trở nên lộn xộn khi bạn cố gắng kéo công việc của họ trở lại với 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.