Làm cách nào để khôi phục từ một bản gốc gốc git push -f bị lỗi?


93

Tôi chỉ phạm sai nguồn cho --forcetùy chọn sử dụng dự án của tôi .

Có thể hoàn nguyên không? Tôi hiểu rằng tất cả các nhánh trước đó đã bị ghi đè bằng cách sử dụng -ftùy chọn, vì vậy tôi có thể đã làm hỏng các bản sửa đổi trước của mình.


Câu trả lời:


55

Git thường không vứt bỏ bất cứ thứ gì, nhưng việc khôi phục sau điều này có thể vẫn còn khó khăn.

Nếu bạn có nguồn chính xác thì bạn chỉ cần đẩy nó vào điều khiển từ xa với --forcetùy chọn. Git sẽ không xóa bất kỳ nhánh nào trừ khi bạn đã yêu cầu. Nếu bạn đã thực sự mất các cam kết thì hãy xem hướng dẫn hữu ích này để khôi phục các cam kết . Nếu bạn biết SHA-1 của các cam kết mà bạn muốn thì có lẽ bạn đã OK.

Điều tốt nhất nên làm: Sao lưu mọi thứ và xem những gì vẫn còn trong kho lưu trữ cục bộ của bạn. Làm tương tự trên điều khiển từ xa nếu có thể. Sử dụng git fsckđể xem liệu bạn có thể khôi phục mọi thứ, và trên hết là KHÔNG chạygit gc .

Trên hết, không bao giờ sử dụng --forcetùy chọn trừ khi bạn thực sự, thực sự có ý nghĩa với nó.


64
Bạn rất có thể chỉ cần xem các bản ghi lại để xác định vị trí ban đầu của các chi nhánh ở xa. Ví dụ git reflog show remotes/origin/master,. Bạn sẽ có thể thấy sự thúc đẩy của bạn trong đó; cam kết ở dòng trước là nơi nó ở trước khi bạn làm rối nó. Sau đó, bạn có thể chỉ cần đẩy bản sửa đổi đó (với --force) về nguồn gốc và quay lại vị trí cũ của bạn!
Cascabel

@David: Ồ. Bạn đã không đề cập trong câu hỏi của mình rằng bạn không có repo. (Tất nhiên đây là điều bạn không bao giờ muốn làm.) Tuy nhiên, nếu bạn có quyền truy cập hệ thống tệp ở nơi bạn đã đẩy đến, bạn vẫn có thể làm tất cả những điều này ở đó.
Cascabel

1
@David: Rất tiếc. Luôn luôn tốt để có thư mục hiện tại của bạn như là một phần của lời nhắc để tránh những điều như vậy.
Cascabel

1
@Jefromi Tôi nghĩ những gì bạn nói là có thực tế: Ngay cả với một phiên bản cũ (không có chỉnh sửa git fetchtrong một thời gian dài), bạn có thể hiển thị bản cập nhật của phía GitHub và khôi phục!
nh2 13/09/12

1
Câu trả lời này ở đâu bởi @Jefromi? Tôi không thấy người dùng đó được đề cập trên trang này bên ngoài chuỗi bình luận này.
Don McCurdy

47

Nếu bạn biết mã băm cam kết, thật dễ dàng, chỉ cần tạo lại nhánh của bạn.

5794458...b459f069 master -> master (forced update)

Xóa chi nhánh từ xa:

git push origin :master

sau đó tạo lại nhánh của bạn bằng các lệnh sau:

git checkout 5794458
git branch master
git push origin master

28

Giải pháp đã được đề cập ở đây

# work on local master
git checkout master

# reset to the previous state of origin/master, as recorded by reflog
git reset --hard origin/master@{1}

# at this point verify that this is indeed the desired commit.
# (if necessary, use git reflog to find the right one, and
# git reset --hard to that one)

# finally, push the master branch (and only the master branch) to the server
git push -f origin master

Cảm ơn bạn, điều này đã làm việc cho tôi. Tôi không có quyền truy cập để xóa trang cái nên nhận xét được phê duyệt không thành công.
Andi

Có, và git reflog show remotes/origin/masternếu git reflog là cần thiết (như @Cascabel đã đề cập ở trên)
Josiah Yoder

2
Đây là câu trả lời chính xác, cảm ơn bạn đã liên kết đến câu trả lời chính xác.
Noitidart

6

Nếu bạn không ở trên repo cục bộ nơi bắt buộc đẩy đến từ cấp độ gốc / cấp độ chính thì không có cách nào để khôi phục. Nhưng nếu bạn đủ may mắn để sử dụng GitHub hoặc GitHub cho Doanh nghiệp , bạn có thể xem REST API và lấy lại cam kết bị mất dưới dạng bản vá, ví dụ:

  1. Liệt kê các sự kiện và tìm định dạng dài cam kết sha1

https://api.github.com/repos/apache/logging-log4j2/events

  1. Tải xuống cam kết bị mất và truy xuất bản vá liên quan trong đường dẫn json .files [] / patch

https://api.github.com/repos/apache/logging-log4j2/commits/889232e28f3863d2a17392c06c1dd8cac68485de

  1. Áp dụng cục bộ và đẩy lại

git áp dụng patch.patch && git commit -m "restore commit" && git push origin master


4

Một cách khác để khôi phục cam kết bị mất hoặc thậm chí để tìm ra những cam kết nào đã bị mất, nếu lần đẩy trước đó không phải từ repo cục bộ của bạn, là xem máy CI của bạn.

Nếu bạn có một công việc kiểm tra nhánh chính sau mỗi lần cam kết (hoặc một loạt các lần cam kết liên tiếp), mà bạn nên có, bạn có thể xem nó đã kiểm tra lần trước. Đó là cam kết bạn cần khôi phục.

Máy CI thậm chí có thể giữ một bản sao cục bộ của repo, từ đó bạn có thể thực hiện khôi phục này.

Nguồn: có lẽ Phân phối liên tục: Bản phát hành phần mềm đáng tin cậy thông qua Tự động hóa xây dựng, kiểm tra và triển khai (Dòng chữ ký Addison-Wesley (Fowler))


3

Có, bạn có thể khôi phục các cam kết sau khi git push -f your_branch

Văn bản từ Doc :

Tỉa các mục cũ hơn thời gian quy định. Nếu tùy chọn này không được chỉ định, thời gian hết hạn được lấy từ cài đặt cấu hình gc.reflogExpire, lần lượt được mặc định là 90 ngày. --expire = tất cả các mục nhập mận khô bất kể tuổi của chúng; --expire = không bao giờ tắt lược bớt các mục có thể truy cập (nhưng xem --expire-không thể truy cập).

Vì vậy, bạn có thể làm:

1- git reflog

nhập mô tả hình ảnh ở đây

2- bạn chọn Head_Number bạn có muốn khôi phục git reset –hard HEAD@{HEAD-NUMBER}

nhập mô tả hình ảnh ở đây

3- bạn có thể thấy tất cả các cam kết trên đầu này bằng cách git cherry -v branch_name

4- cuối cùng bạn nên ép git push -f branch_name

HOẶC LÀ

1- lấy số SHA từ ứng dụng khách GIT của bạn (giao diện)

git reset --hard commit_SHA

2- lực đẩy

git push -f your_branch

Hi vọng điêu nay co ich


2

Tôi đã làm điều tương tự khi hoàn tác lần đẩy cuối cùng chỉ cho một tệp. Đã kết thúc để quay lại trạng thái ban đầu của kho lưu trữ. Tôi đang sử dụng lệnh git từ Linus khi tôi có bản sao cục bộ trên Linux. May mắn thay, bản sao đó vẫn còn nguyên vẹn.

Tất cả những gì tôi đã làm là (sau khi điên cuồng tạo thêm một vài bản sao của repo cục bộ):

git add .
git status

(nó nói rằng origin / master đã đi trước 68 commit, tốt thôi ... đó là tất cả các commit mà tôi đã xóa)

git remote set-url origin <GIT_SSH_URL>
git push

Và mọi thứ đã khôi phục lại như cũ trước khi tôi thực hiện động tác đẩy mạnh. Điều quan trọng nhất cần nhớ là không bao giờ thực hiện kiểm tra git. sau khi bạn đã ấn mạnh. Nhưng cách tốt nhất là tắt tùy chọn đẩy. Tôi không bao giờ sử dụng nó nữa. Rút ra bài học của tôi !!


1

Đối với những người ở trong tình huống thực sự tồi tệ như tôi (ví dụ: nếu bạn gặp bad objectlỗi khi chạy git reset --hard):

Tôi đã viết một tập lệnh có tên là trình bảo vệ cây để kéo tất cả các tệp của bạn từ API GitHub như một phương sách cuối cùng. Đây là cách sử dụng nó:

  1. Sao chép treesaverscript và cdnó.
  2. Tìm SHAchuỗi cây mà bạn muốn khôi phục bằng cách truy cập https://api.github.com/repos/<your_username_or_org>/<repo>/events.
  3. Trong thuộc payloadtính tương ứng với sự kiện đẩy của bạn, hãy tìm thuộc tính commitbạn muốn hoàn nguyên và nhấp vào thuộc tính đó url.
  4. Dưới commit.tree, sao chép tree's url.
  5. Chạy đi python3 main.py <tree_url> <path_to_save_to>.

Ví dụ, trong trường hợp của tôi, tôi sẽ chạy:

python3 main.py https://api.github.com/repos/anthonykrivonos/my-repo/git/trees/1234567 .

Tất nhiên, các PR được hoan nghênh.


0

Tại đây bạn có thể đọc các quyết định https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it

Cái thứ hai đã giúp tôi. Tôi đã làm sai những lệnh này

1) (some-branch) git pull -> correct command was git pull origin some-branch

2) (some-branch) git push -f origin some-branch

Sau những lệnh này, tôi đã mất ba lần cam kết. Để khôi phục chúng, tôi đã tìm đến thiết bị đầu cuối, nơi tôi đã làm sai 'git pull' và đã thấy có kết quả như

60223bf ... 0b258eb some-branch -> origin / some-branch

Hàm băm thứ hai 0b258eb là chính xác những gì tôi cần. Vì vậy, tôi đã lấy lệnh băm và sản xuất này

git push --force origin 0b258eb:some-branch
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.