Làm thế nào để hoàn nguyên cam kết git ban đầu?


357

Tôi cam kết với một kho lưu trữ git lần đầu tiên; Sau đó tôi hối hận về cam kết và muốn hoàn nguyên nó. tôi thử

# git reset --hard HEAD~1

Tôi nhận được tin nhắn này:

fatal: ambiguous argument 'HEAD~1': unknown revision or path not in the working tree.

Cam kết này là cam kết đầu tiên của kho lưu trữ. Bất kỳ ý tưởng làm thế nào để hoàn tác cam kết ban đầu của git?

Câu trả lời:


565

Bạn chỉ cần xóa chi nhánh bạn đang ở. Bạn không thể sử dụng git branch -Dvì điều này có kiểm tra an toàn chống lại việc này. Bạn có thể sử dụng update-refđể làm điều này.

git update-ref -d HEAD

Đừng không sử dụng rm -rf .githoặc bất cứ điều gì như thế này vì điều này sẽ hoàn toàn xóa sạch toàn bộ kho của bạn bao gồm tất cả các chi nhánh khác cũng như các chi nhánh mà bạn đang cố gắng để thiết lập lại.


1
Đã thử điều này trong khi trong một cuộc nổi loạn - muốn phân chia cam kết đầu tiên - sau đó đã làm git status, và tôi ngạc nhiên, git nói fatal: Not a git repository (or any parent up to mount point ...)!
Matt Fenwick

1
điều này đã không làm việc cho tôi. Tạo các tệp bao gồm một số nên bỏ qua nhưng không .gitignore. git add ., git commit -m "initial commit", git update-ref -D HEAD, Tạo .gitignore, thông báo rằng git vẫn được nhìn thấy các tập tin nó thêm trước đó nên bỏ qua. Nói cách khác, tôi git update-ref -d HEADđã không đưa tôi trở lại trạng thái trước khi cam kết ban đầu.
gman

1
Nhưng đó là điểm của câu hỏi ban đầu. Quay trở lại trạng thái ngay trước khi cam kết ban đầu.
gman

2
git reset --hard HEAD~1sẽ loại bỏ các tập tin được thêm vào cho tất cả các cam kết khác. Rõ ràng câu hỏi là làm thế nào để đến trạng thái giống như lệnh đó hoạt động trong tất cả các trường hợp khác. Xem ý chính này để chứng minh giải pháp của bạn không hoạt động gist.github.com/greggman/522fa69a21d6cfb3ff0b
gman

11
Trong trường hợp bất cứ ai bị nhầm lẫn bởi comments GMAN của: git update-ref -d HEAD không thực sự trở lại cam kết ban đầu, nhưng giữ tất cả những thay đổi cam kết trước đó thêm vào chỉ mục. Nếu bạn cũng muốn loại bỏ những thay đổi đó, chỉ cần thực hiện như sau git reset --hard. Ngay cả khi không đầy đủ, câu trả lời này thực sự là câu trả lời tốt nhất, vì vậy hãy tránh sử dụng rm -fr .git(trừ khi bạn biết bạn đang làm gì).
rsenna

62

Bạn có thể xóa CHÍNH và khôi phục kho lưu trữ của mình sang trạng thái mới, nơi bạn có thể tạo một cam kết ban đầu mới:

git update-ref -d HEAD

Sau khi bạn tạo một cam kết mới, nếu bạn đã đẩy sang điều khiển từ xa, bạn sẽ cần buộc nó vào điều khiển từ xa để ghi đè lên cam kết ban đầu trước đó:

git push --force origin

1
Đáng chú ý ... đây là lệnh chính xác nhưng nó không xóa CHÍNH ... nó xóa ref (nằm dưới .git \ refs \ Heads) mà tệp .git \ HEAD đã kiểm tra. Sau khi chạy lệnh này, bạn vẫn có thể tìm thấy tệp CHÍNH chỉ vào tệp refs / Heads / <name> mà bạn đã xóa nhưng nếu bạn đi theo đường dẫn đó, bạn sẽ thấy rằng các đầu ref không còn tồn tại.
DanK

15

Câu hỏi này được liên kết từ bài đăng trên blog này và một giải pháp thay thế đã được đề xuất cho các phiên bản mới hơn của Git:

git branch -m master old_master
git checkout --orphan master
git branch -D old_master

Giải pháp này giả định rằng:

  1. Bạn chỉ có một cam kết trên masterchi nhánh của mình
  2. Không có chi nhánh nào được gọi old_masternên tôi tự do sử dụng tên đó

Nó sẽ đổi tên nhánh hiện có thành old_mastervà tạo một nhánh mới, mồ côi, master (giống như nó được tạo cho các kho lưu trữ mới) sau đó bạn có thể tự do xóa old_master... hoặc không. Tùy bạn

Lưu ý: Di chuyển hoặc sao chép một nhánh git sẽ duy trì reflog của nó (xem mã này ) trong khi xóa và sau đó tạo một nhánh mới phá hủy nó. Vì bạn muốn quay lại trạng thái ban đầu mà không có lịch sử, bạn có thể muốn xóa chi nhánh, nhưng những người khác có thể muốn xem xét ghi chú nhỏ này.


11

Theo các điều kiện quy định trong câu hỏi:

  • Cam kết là cam kết đầu tiên trong kho lưu trữ.
  • Điều đó có nghĩa là đã có rất ít lệnh được thực thi:
    • một git init,
    • có lẽ một số git addhoạt động,
    • git commit,
    • và đó là tất cả!

Nếu những điều kiện tiên quyết đó được đáp ứng, thì cách đơn giản nhất để hoàn tác cam kết ban đầu sẽ là:

rm -fr .git

từ thư mục nơi bạn đã làm git init. Sau đó, bạn có thể làm lại git initđể tạo lại kho Git và làm lại các bổ sung với bất kỳ thay đổi nào là hợp lý mà bạn hối tiếc vì đã không thực hiện lần đầu tiên và làm lại cam kết ban đầu.

NGUY HIỂM! Điều này loại bỏ thư mục kho Git.

Nó xóa thư mục kho Git vĩnh viễn và không thể phục hồi, trừ khi bạn có bản sao lưu ở đâu đó. Theo các điều kiện tiên quyết, bạn không có gì bạn muốn giữ trong kho lưu trữ, vì vậy bạn sẽ không mất gì cả. Tất cả các tệp bạn đã thêm vẫn có sẵn trong các thư mục làm việc, giả sử bạn chưa sửa đổi chúng và chưa xóa chúng, v.v. Tuy nhiên, việc này chỉ an toàn nếu bạn không có gì khác trong kho lưu trữ của mình. Trong các trường hợp được mô tả trong câu hỏi 'cam kết kho lưu trữ lần đầu tiên - sau đó hối tiếc', nó an toàn. Rất thường xuyên, mặc dù, nó không an toàn.

Nó cũng an toàn để làm điều này để loại bỏ một kho lưu trữ nhân bản không mong muốn; nó không làm hỏng kho lưu trữ mà nó được nhân bản từ đó. Nó sẽ loại bỏ mọi thứ bạn đã làm trong bản sao của mình, nhưng không ảnh hưởng đến kho lưu trữ ban đầu.

Hãy cẩn thận, nhưng nó an toàn và hiệu quả khi các điều kiện tiên quyết được đáp ứng.

Nếu bạn đã thực hiện những việc khác với kho lưu trữ mà bạn muốn bảo tồn, thì đây không phải là kỹ thuật phù hợp - kho lưu trữ của bạn không còn đáp ứng các điều kiện tiên quyết để điều này phù hợp.


9
Đây là lời khuyên tồi. Điều gì xảy ra nếu có những thứ khác trong repo mà bạn không muốn mất?
Matt Fenwick

5
Sau đó, nó sẽ không phải là cam kết ban đầu, phải không. Chỉ có một cam kết ban đầu.
Jonathan Leffler

9
"Sau đó, nó sẽ không phải là cam kết ban đầu" - thực sự, đúng vậy. Bạn đang bỏ qua trường hợp rất phổ biến của nhiều chi nhánh. Xem câu trả lời của Charles.
Matt Fenwick

2
Hữu ích, tuy nhiên nên đi kèm với một cảnh báo.
Simon Bengtsson

5
Điều này thực sự hoạt động. Câu trả lời được chấp nhận không. Xem bình luận
gman

3

Bạn không thể. Vì thế:

rm -rf .git/
git init
git add -A
git commit -m 'Your new commit message'

1
Anh cố nói git reset --hard, vậy tại sao anh git add -A?
Aristotle Pagaltzis

3

Tôi sẽ ném vào những gì làm việc cho tôi cuối cùng. Tôi cần xóa cam kết ban đầu trên kho lưu trữ vì dữ liệu đã cách ly đã bị đặt sai vị trí, cam kết đã bị đẩy.

Hãy chắc chắn rằng bạn đang ở trên nhánh phải.

git checkout master

git update-ref -d HEAD

git commit -m "Initial commit

git push -u origin master

Điều này đã có thể giải quyết vấn đề.

Quan trọng

Đây là trên một kho lưu trữ nội bộ không thể truy cập công khai, nếu kho lưu trữ của bạn có thể truy cập công khai, vui lòng giả sử mọi thứ bạn cần hoàn nguyên đã bị người khác kéo xuống.


1

Tôi tự hỏi tại sao "sửa đổi" không được đề xuất và đã bị @damkrat gạch bỏ, vì sửa đổi dường như là cách đúng đắn để giải quyết vấn đề cơ bản nhất trong việc sửa lỗi cam kết vì không có mục đích ban đầu cam kết. Như một số người nhấn mạnh, bạn chỉ nên sửa đổi chi nhánh "công khai" như chủ nếu không có ai sao chép repo của bạn ...

git add <your different stuff>
git commit --amend --author="author name <author.name@email.com>"-m "new message"

- chỉ được yêu cầu tác giả nếu ai đó sửa quyền tác giả của cam kết
Richard

0

git reset - hãy thực hiện thay đổi, sau đó thực hiện

git add -A
git commit --amend --no-edit 

hoặc là

git add -A
git commit --amend -m "commit_message"

và sau đó

git push origin master --force

--force sẽ viết lại cam kết mà bạn đã đặt lại ở bước đầu tiên.

Đừng làm điều này, bởi vì bạn sắp đi ngược lại toàn bộ ý tưởng về các hệ thống và đặc biệt là VCS. Phương pháp tốt duy nhất là tạo mới và xóa chi nhánh không cần thiết. Xem git help branchđể biết thông tin.


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.