Quay lại kho lưu trữ git cục bộ và từ xa bằng 1 lần xác nhận


187

Tôi đã đọc những bài viết tương tự về chủ đề này và không thể tìm ra cách làm điều này đúng cách.

Tôi đã kiểm tra khoảng 1000 tệp mà tôi không muốn và tôi không phải trải qua 1by1 và xóa tất cả chúng khỏi repo.

  • Tôi có một masterchi nhánh từ xa .
  • Tôi có masterChi nhánh địa phương .

Cả hai đều ở cùng một phiên bản.

Tôi muốn khôi phục từ xa của tôi bằng 1 cam kết.

Nói lịch sử của tôi trên masterA--B--C--D--E.
Tôi muốn quay trở lại địa phương của tôi để D.
Sau đó đẩy nó ra từ xa để hàm băm hiện tại của tôi sẽ là D cả từ xa và cục bộ.

Tôi đang có vấn đề làm điều này.
Tôi đang sử dụng Git Tower nhưng thoải mái với dòng lệnh. Có ai giúp đỡ không?

CẬP NHẬT: Những bình luận tuyệt vời dưới đây. Sử dụng thiết lập lại dường như không được khuyến khích một phần, đặc biệt nếu kho lưu trữ được chia sẻ với người dùng khác. Cách tốt nhất để hoàn tác các thay đổi của cam kết trước đó mà không cần sử dụng thiết lập lại cứng ? Là có một cách?


Tôi đã cập nhật câu trả lời của mình để "hoàn tác các thay đổi của cam kết trước đó mà không cần sử dụng thiết lập lại cứng".
VonC

3
Sử dụng git revertđể làm mà không cần thiết lập lại cứng và không làm phiền người dùng.
dùng562374


Quay ngược lại điều khiển từ xa là điều không được khuyến khích, nhưng nếu đó là điều bạn muốn làm, hãy làm điều đó. Có hàng trăm cách để làm điều đó, nhưng kết quả sẽ giống nhau ở phía máy chủ.
FelipeC

Câu trả lời:


306

Nếu chưa có ai kéo repo từ xa của bạn, bạn có thể thay đổi chi nhánh CHÍNH của mình và buộc đẩy nó sang repo từ xa:

git reset --hard HEAD^ 
git push -f 

(hoặc, nếu bạn có quyền truy cập trực tiếp vào repo từ xa, bạn có thể thay đổi tham chiếu CHÍNH của nó ngay cả khi đó là repo trần )

Lưu ý, như nhận xét của công nghệ ngoài hành tinh trong các bình luận bên dưới , trên Windows (phiên CMD), bạn sẽ cần ^^:

git reset --hard HEAD^^
git push -f 

Cập nhật từ năm 2011:
Sử dụng git push --force-with-lease( mà tôi trình bày ở đây , được giới thiệu vào năm 2013 với Git 1.8.5) sẽ an toàn hơn.

Xem câu trả lời của Schwern để minh họa.


Nếu ai đó đã kéo repo thì sao? Tôi sẽ làm gì sau đó?

Sau đó, tôi sẽ đề xuất một cái gì đó không viết lại lịch sử:

  • git revert cục bộ cam kết cuối cùng của bạn (tạo một cam kết mới đảo ngược những gì cam kết trước đó đã làm)
  • đẩy 'hoàn nguyên' được tạo bởi git revert.

1
Nếu ai đó đã kéo repo thì sao? Tôi sẽ làm gì sau đó?
Jamis Charles

1
@gwho tạo chi nhánh? Không, nó di chuyển đầu của một nhánh, nhưng bạn vẫn ở trong cùng một nhánh. Tuy nhiên, vì cú đẩy không còn là một cú đẩy nhanh nữa, nên, bạn cần phải đẩy lực đẩy đó.
VonC

1
Có cách nào để biết nếu ai đó đã kéo repo?
Pinkerton

4
Trong Windows, ký tự ^ được sử dụng để tiếp tục dòng và để thoát một ký tự, thực hiện lệnh: git reset --hard Head ^^
Alien Technology

1
@ AlienT Technology Sử dụng Powershell, trên windows 10, tôi chỉ phải gõ reset --hard HEAD^và không reset --hard HEAD^^thiết lập lại cam kết cuối cùng.
Gaspacchio

56

Đặt lại bản sửa đổi chi nhánh địa phương ( HEAD^có nghĩa là một bản sửa đổi trở lại):

git reset --hard HEAD^

Đẩy các thay đổi về nguồn gốc:

git push --force

Bạn sẽ phải ép buộc vì nếu không git sẽ nhận ra rằng bạn đứng sau originmột cam kết và sẽ không có gì thay đổi.

Làm điều đó với --forcegit để ghi đè lên HEADrepo từ xa mà không tôn trọng bất kỳ tiến bộ nào ở đó.


1
Tôi đề nghị không gọi đây là hoàn nguyên, vì đó là một thuật ngữ cụ thể với ý nghĩa rất khác trong git.
Cascabel

@Jefromi: Cảm ơn bạn đã gợi ý. Đã chỉnh sửa.
eckes

Câu trả lời chính xác. Tôi đã đọc được rằng sử dụng thiết lập lại dường như không được khuyến khích một phần, đặc biệt nếu kho lưu trữ được chia sẻ với người dùng khác. Có cách nào sạch hơn để làm điều này, đó là hoàn tác tất cả các thay đổi của cam kết trước đó của bạn không?
Jamis Charles

Hãy cẩn thận! Bỏ bớt những thay đổi không được cam kết của bạn hoặc bạn đã mất chúng
Nosov Pavel

Thật tuyệt. Vì vậy, điều này có nghĩa là khi chúng tôi làm git push origin master, Git có thể tạo một cam kết mới ở xa vì chi nhánh địa phương đi trước ít nhất một lần cam kết? Hơn nữa, cái sau phải khác biệt đáng kể so với cái đầu ở repo từ xa chỉ vào cái gì?
MadPhysicist

18

Nếu bạn muốn hoàn nguyên cam kết cuối cùng hãy lắng nghe:

Bước 1:

Kiểm tra cam kết địa phương của bạn với tin nhắn

$ git log

Bước 2:

Xóa cam kết cuối cùng mà không đặt lại các thay đổi từ nhánh cục bộ (hoặc chính)

$ git reset HEAD^

HOẶC nếu bạn không muốn tập tin cam kết cuối cùng và cập nhật lắng nghe

$ git reset HEAD^ --hard

Bước 3:

Chúng tôi có thể cập nhật các tập tin và mã và một lần nữa cần đẩy mạnh bằng cách nó sẽ xóa cam kết trước đó. Nó sẽ giữ cam kết mới.

$ git push origin branch -f

Đó là nó!


Đó không phải là hoàn trả một cam kết, nó thay thế một cam kết. Xin đừng nhầm lẫn chúng tôi git người mới bằng cách sử dụng sai các thuật ngữ thông thường.
Suncat2000

7

Bằng cách nhập lệnh dưới đây, bạn có thể thấy lịch sử cam kết git của mình -

$ git nhật ký

Giả sử lịch sử của bạn trên chi nhánh cụ thể đó giống như - commit_A, commit_B, commit_C, commit_D. Trong đó, commit_D là lần xác nhận cuối cùng và đây là nơi vẫn còn CHÍNH. Bây giờ, để xóa cam kết cuối cùng của bạn khỏi cục bộ và từ xa, bạn cần làm như sau:

Bước 1: Xóa cam kết cuối cùng cục bộ bằng cách -

$ git đặt lại - đầu trang ~

Điều này sẽ thay đổi CHÍNH cam kết của bạn thành commit_C

Bước 2: Đẩy thay đổi của bạn cho cam kết CHÍNH mới vào điều khiển từ xa

$ git đẩy nguồn gốc + ĐẦU

Lệnh này sẽ xóa cam kết cuối cùng từ xa.

PS lệnh này được thử nghiệm trên Mac OSX và cũng sẽ hoạt động trên các hệ điều hành khác (không yêu cầu về hệ điều hành khác)



2

Đây là phiên bản cập nhật của quy trình an toàn hơn.

git reset --hard HEAD^ 
git push --force-with-lease

git push -fsẽ thay thế bừa bãi kho lưu trữ từ xa bằng các thay đổi của riêng bạn. Nếu ai đó đã thúc đẩy thay đổi, họ sẽ bị mất.git push --force-with-leasesẽ chỉ đẩy rebase của bạn nếu kho lưu trữ như bạn mong đợi. Nếu ai đó đã đẩy thì cú đẩy của bạn sẽ thất bại.

Xem lực lượng được coi là có hại; hiểu được git'sforceforce-with-cho thuê .

Tôi khuyên bạn nên răng cưa này như repush = push --force-with-lease.

Nếu ai đó đã kéo repo thì sao? Tôi sẽ làm gì sau đó?

Nói với họ để git pull --rebase=merges. Thay vì một git fetch origingit merge origin/masternó sẽ git fetch origingit rebase -r origin/master. Điều này sẽ viết lại bất kỳ thay đổi cục bộ nào của họ lên mastertrên đỉnh của cuộc nổi loạn mới origin/master. -rsẽ bảo tồn bất kỳ sự hợp nhất nào họ có thể đã thực hiện.

Tôi khuyên bạn nên làm điều này là hành vi mặc định để kéo. Nó là an toàn, sẽ xử lý các cuộc nổi loạn của người khác, và kết quả là sự hợp nhất ít cần thiết hơn.

[pull]
        rebase = merges

1
Đồng ý, và nâng cao. Để bảo vệ tôi, câu trả lời năm 2011 cũ của tôi đã được viết hai năm trước khi đưa ra --force-with-leaselựa chọn.
VonC

Tôi nghĩ rằng tôi đã làm điều đó rồi (ngày hôm qua): stackoverflow.com/posts/4647362/revutions
VonC

1

Tôi đã giải quyết vấn đề như của bạn bằng các lệnh này:

git reset --hard HEAD^
git push -f <remote> <local branch>:<remote branch> 


0

Tôi chỉ muốn xóa cam kết cuối cùng từ xa và xóa lịch sử cam kết cũng có. Sau đây làm việc như một nét duyên dáng

git reset --hard HEAD^ 
git push -f 

Nhưng làm thế nào "sau đây" khác với câu trả lời của tôi ở trên ?
VonC

0

Cách để thiết lập lại đầu và thực hiện hoàn nguyên về cam kết trước đó là thông qua

$ git reset HEAD^ --hard
$ git push <branchname> -f

Nhưng đôi khi nó có thể không được chấp nhận trong nhánh từ xa:

To ssh:<git repo>
 ! [rejected]        develop -> develop (non-fast-forward)
error: failed to push some refs to 'ssh:<git repo>'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

sau đó, cách khác để làm là

git revert HEAD
git push <remote branch>

Điều này hoạt động tốt.

LƯU Ý: hãy nhớ nếu git push -f <force>thất bại và sau đó bạn cố gắng hoàn nguyên. Thực hiện git pulltrước, để từ xa và cục bộ được đồng bộ hóa và sau đó thử git revert.
Kiểm tra git logđể đảm bảo điều khiển từ xa và cục bộ tại cùng một điểm cam kết với cùng SHA1 ..

git revert 
A --> B --> C -->D
A--> B --> C --> D --> ^D(taking out the changes and committing reverted diffs)

0

về chủ địa phương

git reflog
-- this will list all last commit
  e.g Head@{0} -- wrong push
      Head@{1} -- correct push  
git checkout Head@{1} .
  -- this will reset your last modified files

git status 
git commit -m "reverted to last best"
git push origin/master

Không cần phải lo lắng nếu khác có kéo hay không.

Làm xong!


0

Nếu bạn chỉ muốn xóa cam kết cuối cùng khỏi kho lưu trữ từ xa mà không làm phiền với kho lưu trữ cục bộ của mình, thì đây là một lớp lót:

git push origin +origin/master~:master

Điều này sử dụng cú pháp sau:

git push <remote> <refspec>

Đây, <remote>origin, và <refspec>có cấu trúc sau:

+origin/master~:master

Thông tin chi tiết có thể được tìm thấy trong git-push(1). Phần trước +có nghĩa là "lực đẩy ref này" và phần khác có nghĩa là "từ origin/master~đến master(từ xa origin)". Không khó để biết đó origin/master~là cam kết cuối cùng trước đây origin/master, phải không?


0

Đối với tôi, hai lệnh này:

git checkout commit_id
git push origin +name_of_branch

0

Bạn cũng có thể làm điều này:

git reset --hard <commit-hash>
git push -f origin master

và có tất cả những người khác đã thiết lập lại cam kết xấu mới nhất:

git reset --hard origin/master
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.