it-swarm-vi.com

Cách hoàn nguyên kho lưu trữ Git về một cam kết trước đó

Làm cách nào để tôi hoàn nguyên từ trạng thái hiện tại của mình sang ảnh chụp nhanh được thực hiện trên một cam kết nhất định?

Nếu tôi làm git log, thì tôi nhận được đầu ra sau:

$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <[email protected]>
Date:   Thu Nov 4 18:59:41 2010 -0400

blah blah blah...

commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <[email protected]>
Date:   Thu Nov 4 05:13:39 2010 -0400

more blah blah blah...

commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <[email protected]>
Date:   Thu Nov 4 00:55:06 2010 -0400

And yet more blah blah...

commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <[email protected]>
Date:   Wed Nov 3 23:56:08 2010 -0400

Yep, more blah blah.

Làm cách nào để hoàn nguyên cam kết từ ngày 3 tháng 11, tức là cam kết 0d1d7fc?

6795
Crazy Serb

Điều này phụ thuộc rất nhiều vào ý nghĩa của bạn khi "hoàn nguyên".

Tạm thời chuyển sang một cam kết khác

Nếu bạn muốn tạm thời quay lại với nó, đánh lừa xung quanh, sau đó quay lại nơi bạn đang ở, tất cả những gì bạn phải làm là kiểm tra cam kết mong muốn:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

Hoặc nếu bạn muốn thực hiện các cam kết trong khi bạn ở đó, hãy tiếp tục và tạo một chi nhánh mới trong khi bạn ở đó:

git checkout -b old-state 0d1d7fc32

Để quay trở lại nơi bạn đang ở, chỉ cần kiểm tra chi nhánh bạn đã ở lại. (Nếu bạn đã thực hiện thay đổi, như mọi khi khi chuyển đổi chi nhánh, bạn sẽ phải đối phó với chúng khi thích hợp. Bạn có thể đặt lại để vứt chúng đi; họ đến một chi nhánh ở đó nếu bạn muốn một chi nhánh ở đó.)

Xóa cứng các cam kết chưa được công bố

Mặt khác, nếu bạn muốn thực sự loại bỏ mọi thứ bạn đã làm kể từ đó, có hai khả năng. Một, nếu bạn chưa công bố bất kỳ cam kết nào trong số này, chỉ cần đặt lại:

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.

Nếu bạn gây rối, bạn đã vứt bỏ các thay đổi cục bộ của mình, nhưng ít nhất bạn có thể quay lại nơi bạn đã ở trước đó bằng cách đặt lại lần nữa.

Hoàn tác các cam kết được công bố với các cam kết mới

Mặt khác, nếu bạn đã xuất bản tác phẩm, có lẽ bạn không muốn đặt lại chi nhánh, vì đó là cách viết lại lịch sử một cách hiệu quả. Trong trường hợp đó, bạn thực sự có thể hoàn nguyên các cam kết. Với Git, Revert có một ý nghĩa rất cụ thể: tạo một cam kết với bản vá ngược để hủy bỏ nó. Bằng cách này, bạn không viết lại bất kỳ lịch sử.

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053 

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

Trang chủ git-revert thực sự bao gồm rất nhiều điều này trong mô tả của nó. Một liên kết hữu ích khác là phần git-scm.com này thảo luận về git-Revert .

Nếu bạn quyết định cuối cùng bạn không muốn hoàn nguyên, bạn có thể hoàn nguyên hoàn nguyên (như được mô tả ở đây) hoặc đặt lại về trước khi hoàn nguyên (xem phần trước).

Bạn cũng có thể thấy câu trả lời này hữu ích trong trường hợp này:
[.__.] Làm cách nào để di chuyển HEAD trở lại vị trí trước đó? (Đầu tách rời)

8690
Cascabel

Hoàn nguyên bản sao làm việc để cam kết gần đây nhất

Để trở lại cam kết trước đó, bỏ qua mọi thay đổi:

git reset --hard HEAD

trong đó HEAD là cam kết cuối cùng trong nhánh hiện tại của bạn

Hoàn nguyên Bản sao làm việc cho một Cam kết cũ hơn

Để trở lại một cam kết cũ hơn so với cam kết gần đây nhất:

# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft [email protected]{1}

git commit -m "Revert to 56e05fced"

# Updates working copy to reflect the new commit
git reset --hard

Tín dụng đi đến câu hỏi Stack Overflow tương tự,Hoàn nguyên về một cam kết bằng hàm băm SHA trong Git?.

1451
boulder_ruby

Có rất nhiều câu trả lời phức tạp và nguy hiểm ở đây, nhưng thực sự rất dễ:

git revert --no-commit 0766c053..HEAD
git commit

Điều này sẽ hoàn nguyên mọi thứ từ HEAD trở lại hàm băm xác nhận, nghĩa là nó sẽ tạo lại trạng thái cam kết đó trong cây làm việc như thể mọi cam kết đã được đưa trở lại. Sau đó, bạn có thể cam kết cây hiện tại và nó sẽ tạo ra một cam kết hoàn toàn mới về cơ bản tương đương với cam kết mà bạn "hoàn nguyên".

(Cờ --no-commit cho phép git hoàn nguyên tất cả các cam kết cùng một lúc - nếu không, bạn sẽ được nhắc nhở về một thông báo cho từng cam kết trong phạm vi, xả rác lịch sử của bạn với các cam kết mới không cần thiết.)

Đây là một cách an toàn và dễ dàng để quay trở lại trạng thái trước đó. Không có lịch sử nào bị phá hủy, vì vậy nó có thể được sử dụng cho các cam kết đã được công khai.

1433
Yarin

Tùy chọn tốt nhất cho tôi và có lẽ những người khác là tùy chọn thiết lập lại Git:

git reset --hard <commidId> && git clean -f

Đây là lựa chọn tốt nhất cho tôi! Thật đơn giản, nhanh chóng và hiệu quả!


Lưu ý: Như đã đề cập trong các nhận xét, đừng làm điều này nếu bạn chia sẻ chi nhánh của mình với những người khác có bản sao của các cam kết cũ

Cũng từ các bình luận, nếu bạn muốn một phương pháp 'bóng bẩy' hơn, bạn có thể sử dụng

git clean -i

182
Pogrindis

Trước khi trả lời, hãy thêm một số thông tin cơ bản, giải thích HEAD này là gì.

First of all what is HEAD?

HEAD chỉ đơn giản là một tham chiếu đến cam kết hiện tại (mới nhất) trên nhánh hiện tại. Chỉ có thể có một HEAD duy nhất tại bất kỳ thời điểm nào (không bao gồm git worktree).

Nội dung của HEAD được lưu trữ bên trong .git/HEAD và nó chứa 40 byte SHA-1 của cam kết hiện tại.


detached HEAD

Nếu bạn không tham gia vào cam kết mới nhất - có nghĩa là HEAD đang trỏ đến một cam kết trước đó trong lịch sử, nó được gọi làdetached HEAD.

 Enter image description here

Trên dòng lệnh, nó sẽ trông như thế này - SHA-1 thay vì tên chi nhánh vì HEAD không trỏ đến đầu của nhánh hiện tại:

 Enter image description here


Một vài lựa chọn về cách phục hồi từ một ĐẦU tách ra:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Điều này sẽ kiểm tra chi nhánh mới chỉ vào cam kết mong muốn. Lệnh này sẽ kiểm tra một cam kết nhất định.

Tại thời điểm này, bạn có thể tạo một nhánh và bắt đầu làm việc từ thời điểm này:

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Bạn luôn có thể sử dụng reflog. git reflog sẽ hiển thị bất kỳ thay đổi nào đã cập nhật HEAD và kiểm tra mục nhập reflog mong muốn sẽ đặt HEAD trở lại cam kết này.

Mỗi khi HEAD được sửa đổi, sẽ có một mục mới trong reflog

git reflog
git checkout [email protected]{...}

Điều này sẽ đưa bạn trở lại cam kết mong muốn của bạn

 Enter image description here


git reset HEAD --hard <commit_id>

"Di chuyển" đầu của bạn trở lại cam kết mong muốn.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
  • Lưu ý: ( Vì Git 2.7 ), bạn cũng có thể sử dụng git rebase --no-autostash.

Lược đồ này minh họa lệnh nào làm gì. Như bạn có thể thấy ở đó reset && checkout sửa đổi HEAD.

 Enter image description here

143
CodeWizard

Nếu bạn muốn "không phổ biến", xóa thông báo cam kết cuối cùng và đưa các tệp đã sửa đổi trở lại theo giai đoạn, bạn sẽ sử dụng lệnh:

git reset --soft HEAD~1
  • --soft chỉ ra rằng các tệp không được cam kết sẽ được giữ lại làm các tệp hoạt động trái ngược với --hard sẽ loại bỏ chúng.
  • HEAD~1 là cam kết cuối cùng. Nếu bạn muốn khôi phục 3 cam kết, bạn có thể sử dụng HEAD~3. Nếu bạn muốn quay trở lại một số sửa đổi cụ thể, bạn cũng có thể thực hiện điều đó bằng cách sử dụng hàm băm SHA của nó.

Đây là một lệnh cực kỳ hữu ích trong các tình huống bạn đã phạm phải điều sai và bạn muốn hoàn tác cam kết cuối cùng đó.

Nguồn: http://nakkaya.com/2009/09/24/git-delete-last-commit/

124
Stephen Ostermiller

Tôi đã thử rất nhiều cách để hoàn nguyên các thay đổi cục bộ trong Git và có vẻ như điều này hoạt động tốt nhất nếu bạn chỉ muốn trở lại trạng thái cam kết mới nhất.

git add . && git checkout master -f

Mô tả ngắn:

  • Nó sẽ KHÔNG tạo ra bất kỳ cam kết nào như git revert.
  • Nó sẽ KHÔNG tách HEAD giống như git checkout <commithashcode> của bạn.
  • Nó S over ghi đè tất cả các thay đổi cục bộ của bạn và XÓA tất cả các tệp đã thêm kể từ lần xác nhận cuối cùng trong nhánh.
  • Nó chỉ hoạt động với tên nhánh, vì vậy bạn chỉ có thể hoàn nguyên các cam kết mới nhất trong nhánh theo cách này.

Tôi tìm thấy một cách thuận tiện và đơn giản hơn nhiều để đạt được kết quả ở trên:

git add . && git reset --hard HEAD

trong đó HEAD trỏ đến cam kết mới nhất tại chi nhánh hiện tại của bạn.

Đó là mã mã giống như boulder_Ruby đã đề xuất, nhưng tôi đã thêm git add . trước git reset --hard HEAD để xóa tất cả các tệp mới được tạo kể từ lần xác nhận cuối cùng vì đây là điều mà hầu hết mọi người mong đợi khi tôi quay lại cam kết mới nhất.

105
Roman Minenok

Bạn có thể làm điều này bằng hai lệnh sau:

git reset --hard [previous Commit SHA id here]
git Push Origin [branch Name] -f

Nó sẽ loại bỏ cam kết Git trước đó của bạn.

Nếu bạn muốn giữ các thay đổi của mình, bạn cũng có thể sử dụng:

git reset --soft [previous Commit SHA id here]

Sau đó, nó sẽ lưu các thay đổi của bạn.

94
kiran boghra

OK, quay lại cam kết trước đó trong git khá dễ dàng ...

Hoàn nguyên lại mà không giữ các thay đổi:

git reset --hard <commit>

Hoàn nguyên lại với việc giữ các thay đổi:

git reset --soft <commit>

Giải thích: sử dụng git reset, bạn có thể đặt lại về trạng thái cụ thể, nó phổ biến khi sử dụng nó với hàm băm cam kết như bạn thấy ở trên.

Nhưng như bạn thấy sự khác biệt khi sử dụng hai cờ --soft--hard, theo mặc định git reset sử dụng cờ --soft, nhưng đó là một cách thực hành tốt luôn sử dụng cờ, tôi giải thích từng cờ:


--mềm mại

Cờ mặc định như được giải thích, không cần cung cấp nó, không thay đổi cây làm việc nhưng thêm tất cả các thay đổi tệp sẵn sàng để cam kết, vì vậy bạn quay lại trạng thái cam kết thay đổi tệp không được thực hiện.


--cứng

Hãy cẩn thận với cờ này, nó đặt lại cây làm việc và tất cả các thay đổi đối với các tệp được theo dõi và tất cả sẽ biến mất!


Tôi cũng đã tạo ra hình ảnh dưới đây có thể xảy ra trong cuộc sống thực khi làm việc với git:

 git reset to a commit

63
Alireza

Không có gì ở đây làm việc cho tôi ngoài sự kết hợp chính xác này:

git reset --hard <commit_hash>
git Push Origin <branch_name> --force

Chìa khóa ở đây là buộc Push, không có thêm thông báo cam kết/cam kết, v.v.

59
serdarsenay

Giả sử bạn có các cam kết sau trong tệp văn bản có tên ~/commits-to-revert.txt (Tôi đã sử dụng git log --pretty=oneline để nhận chúng)

fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca

Tạo tập lệnh Bash Shell để hoàn nguyên từng tập lệnh:

#!/bin/bash
cd /path/to/working/copy
for i in `cat ~/commits-to-revert.txt`
do
    git revert $i --no-commit
done

Điều này hoàn nguyên mọi thứ trở lại trạng thái trước đó, bao gồm cả việc tạo tệp và thư mục và xóa, cam kết nó với chi nhánh của bạn và bạn giữ lại lịch sử, nhưng bạn đã hoàn nguyên về cùng cấu trúc tệp. Tại sao Git không có git revert --to <hash> nằm ngoài tôi.

57
Lance Caraccioli

Giải pháp thay thế bổ sung cho các giải pháp của Jefromi

Giải pháp của Jefromi chắc chắn là những giải pháp tốt nhất và bạn chắc chắn nên sử dụng chúng. Tuy nhiên, để hoàn thiện, tôi cũng muốn chỉ ra các giải pháp thay thế khác cũng có thể được sử dụng để hoàn nguyên một cam kết (theo nghĩa là bạn tạo một cam kết mới hoàn tác các thay đổi trong cam kết trước đó , chỉ như những gì git revert làm).

Để rõ ràng, các giải pháp thay thếkhông phải là cách tốt nhất để hoàn nguyên các cam kết, Các giải pháp của Jefromi là , nhưng tôi chỉ muốn chỉ ra rằng bạn cũng có thể sử dụng các phương thức khác này để đạt được điều tương tự như git revert.

Phương án 1: Đặt lại cứng và mềm

Đây là phiên bản sửa đổi rất ít của giải pháp Charles Bailey thành Hoàn nguyên cam kết bằng hàm băm SHA trong Git? :

# Reset the index to the desired commit
git reset --hard <commit>

# Move the branch pointer back to the previous HEAD
git reset --soft [email protected]{1}

# Commit the changes
git commit -m "Revert to <commit>"

Điều này về cơ bản hoạt động bằng cách sử dụng thực tế là các thiết lập lại mềm sẽ rời khỏi trạng thái của cam kết trước đó được đặt trong khu vực chỉ mục/khu vực mà bạn có thể cam kết.

Phương án 2: Xóa cây hiện tại và thay thế bằng cây mới

Giải pháp này xuất phát từ giải pháp của Svick để Thanh toán cam kết cũ và biến nó thành một cam kết mới :

git rm -r .
git checkout <commit> .
git commit

Tương tự như thay thế số 1, điều này tái tạo trạng thái của <commit> trong bản sao làm việc hiện tại. Trước tiên, cần phải làm git rmgit checkout sẽ không xóa các tệp đã được thêm kể từ <commit>.

56
user456814

Giả sử bạn đang nói về chủ và trên chi nhánh tương ứng (có nghĩa là, đây có thể là bất kỳ chi nhánh làm việc nào bạn quan tâm):

# Reset local master branch to November 3rd commit ID
git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50

# Reset remote master branch to November 3rd commit ID
git Push -f Origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master

Tôi tìm thấy câu trả lời từ trong một bài đăng trên blog (bây giờ không còn tồn tại)

Lưu ý rằng đây là Đặt lại và Buộc thay đổi đối với điều khiển từ xa, để nếu những người khác trong nhóm của bạn đã git kéo, bạn sẽ gây ra sự cố cho họ. Bạn đang phá hủy lịch sử thay đổi, đó là một lý do quan trọng tại sao mọi người sử dụng git ngay từ đầu.

Tốt hơn để sử dụng hoàn nguyên (xem câu trả lời khác) hơn là thiết lập lại. Nếu bạn là một đội một người thì có lẽ không vấn đề gì.

55
markreyes

Đây là đơn giản hơn nhiều cách quay lại cam kết trước đó (và để nó ở trạng thái không được cam kết, để thực hiện với bất cứ điều gì bạn muốn):

git reset HEAD~1

Vì vậy, không cần id id và vân vân :)

51
Paul Walczewski

Sau tất cả các thay đổi, khi bạn Đẩy tất cả các lệnh này, bạn có thể phải sử dụng:

git Push -f ...

Và không chỉ git Push.

34
sivi

Có một lệnh (không phải là một phần của lõi Git, nhưng nó nằm trong git-bổ sung gói) đặc biệt để hoàn nguyên và dàn dựng các cam kết cũ:

git back

Trên trang man , nó cũng có thể được sử dụng như sau:

# Remove the latest three commits
git back 3
33
Shadow Man

Bạn có thể tự hoàn thành tất cả các bước ban đầu này và Đẩy lùi để git repo.

  1. Kéo phiên bản mới nhất của kho lưu trữ của bạn từ Bitbucket bằng lệnh git pull --all.

  2. Chạy lệnh git log với -n 4 từ thiết bị đầu cuối của bạn. Số sau -n xác định số lần xác nhận trong nhật ký bắt đầu từ lần xác nhận gần đây nhất trong lịch sử địa phương của bạn.

    $ git log -n 4

  3. Đặt lại phần đầu lịch sử của kho lưu trữ của bạn bằng cách sử dụng git reset --hard HEAD~N trong đó N là số lần xác nhận bạn muốn lấy lại. Trong ví dụ sau, phần đầu sẽ được đặt lại một lần xác nhận, đến lần xác nhận cuối cùng trong lịch sử kho lưu trữ:

  4. Đẩy thay đổi sang git repo bằng cách sử dụng git Push --force để buộc Đẩy thay đổi.

Nếu bạn muốn kho git cho một cam kết trước đó

git pull --all
git reset --hard HEAD~1
git Push --force
29
Nanhe Kumar

Hoàn nguyên về gần đây nhất cam kết và bỏ qua tất cả các thay đổi cục bộ:

git reset --hard HEAD
27

Chọn cam kết yêu cầu của bạn và kiểm tra nó bằng cách

git show HEAD
git show HEAD~1
git show HEAD~2 

cho đến khi bạn nhận được cam kết yêu cầu. Để làm cho HEAD chỉ vào đó, hãy làm

git reset --hard HEAD~1

hoặc git reset --hard HEAD~2 hoặc bất cứ điều gì.

26
tonythomas01

Đây là một cách nữa để trực tiếp thiết lập lại một cam kết gần đây

git stash
git stash clear

Nó trực tiếp xóa tất cả các thay đổi mà bạn đã thực hiện kể từ lần cam kết cuối cùng.

PS: Nó có một vấn đề nhỏ; nó cũng xóa tất cả những thay đổi của bạn được lưu trữ gần đây. Mà tôi đoán trong hầu hết các trường hợp không nên quan trọng.

20
Point Networks

Để giữ các thay đổi từ cam kết trước thành HEAD và chuyển sang cam kết trước đó, hãy làm:

git reset <SHA>

Nếu các thay đổi không được yêu cầu từ cam kết trước đó thành HEAD và chỉ cần loại bỏ tất cả các thay đổi, hãy làm:

git reset --hard <SHA>
20
Vishnu Atrai

Để làm sạch hoàn toàn thư mục của coder khỏi một số thay đổi ngẫu nhiên, chúng tôi đã sử dụng:

git add -A .
git reset --hard HEAD

Chỉ cần git reset --hard HEAD sẽ thoát khỏi các sửa đổi, nhưng nó sẽ không thoát khỏi các tệp "mới". Trong trường hợp của họ, họ đã vô tình kéo một thư mục quan trọng ở đâu đó một cách ngẫu nhiên và tất cả các tệp đó đang được Git coi là mới, vì vậy, một reset --hard đã không sửa nó. Bằng cách chạy git add -A . trước đó, nó đã theo dõi rõ ràng tất cả chúng bằng git, để xóa sạch bằng cách thiết lập lại.

20
Chris Moschini

Tôi tin rằng một số người có thể đến với câu hỏi này muốn biết cách khôi phục các thay đổi đã cam kết mà họ đã thực hiện trong chủ của mình - tức là vứt bỏ mọi thứ và quay lại Origin/master, trong trường hợp này, hãy làm điều này:

git reset --hard Origin/master

https://superuser.com/questions/273172/how-to-reset-master-to-Origin-master

19
nevster

Hoàn nguyên là lệnh để khôi phục các cam kết.

git revert <commit1> <commit2> 

Mẫu vật:

git revert 2h3h23233

Nó có khả năng lấy phạm vi từ HEAD như bên dưới. Ở đây 1 nói "hoàn nguyên cam kết cuối cùng."

git revert HEAD~1..HEAD

và sau đó làm git Push

16
Sireesh Yarlagadda

Hoàn nguyên Cam kết gần đây nhất:

git reset --hard HEAD

HEAD chỉ đơn giản là một tham chiếu đến cam kết hiện tại (mới nhất) trên nhánh hiện tại. Chỉ có thể có một HEAD duy nhất tại bất kỳ thời điểm nào.

Hoàn nguyên về Cam kết cũ hơn: Cách nhanh nhất để khôi phục phiên bản cũ là sử dụng lệnh reset:

# Resets index to former commit
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft [email protected]{1}

# Updates working copy to reflect the new commit
git reset --hard

Điều này sẽ tua lại nhánh HEAD của bạn thành phiên bản đã chỉ định. Tất cả các cam kết xuất hiện sau phiên bản này đều được hoàn tác một cách hiệu quả; dự án của bạn là chính xác như tại thời điểm đó.

Lệnh đặt lại đi kèm với một vài tùy chọn, một trong những tùy chọn thú vị hơn là cờ --soft. Nếu bạn sử dụng nó thay vì --hard, Git sẽ giữ tất cả các thay đổi trong các cam kết "hoàn tác" đó dưới dạng sửa đổi cục bộ.

Khôi phục bản sửa đổi trong Chi nhánh địa phương mới

Như đã nói, sử dụng lệnh đặt lại trên nhánh HEAD của bạn là một hành động khá quyết liệt: nó sẽ xóa mọi cam kết (trên nhánh này) sau khi sửa đổi được chỉ định. Nếu bạn chắc chắn rằng đây là những gì bạn muốn, mọi thứ đều ổn.

Tuy nhiên, cũng có một an toàn hơn cách trong trường hợp bạn muốn rời khỏi nhánh HEAD hiện tại của mình. Vì "các nhánh" rất rẻ và dễ dàng trong Git, chúng tôi có thể dễ dàng tạo một nhánh mới bắt đầu từ phiên bản cũ đó:

git checkout -b old-project-state 0ad5a7a6

Thông thường, lệnh thanh toán được sử dụng để chỉ chuyển đổi các nhánh. Tuy nhiên, cung cấp tham số -b, bạn cũng có thể cho phép nó tạo một nhánh mới (có tên old-project-state trong ví dụ này). Nếu bạn không muốn nó bắt đầu ở phiên bản HEAD hiện tại, bạn cũng cần cung cấp hàm băm cam kết - bản sửa đổi dự án cũ mà chúng tôi muốn khôi phục.

Bây giờ bạn có một nhánh mới có tên old-project-state phản ánh phiên bản cũ của dự án của bạn - mà không cần chạm hoặc thậm chí xóa bất kỳ cam kết hoặc nhánh nào khác.

16
Lyes CHIOUKH

Nếu tình huống là khẩn cấp và bạn chỉ muốn làm những gì người hỏi đã hỏi trong nhanh và bẩn way, giả sử dự án của bạn nằm trong thư mục "dự án của tôi":

  1. Sao chép toàn bộ thư mục và gọi nó là một cái gì đó khác, như "dự án của tôi - sao chép"

  2. Làm:

    git reset --hard [first-4-letters&numbers-of-commit's-SHA]
    

Sau đó, bạn có hai phiên bản trên hệ thống của mình ... bạn có thể kiểm tra hoặc sao chép hoặc sửa đổi các tệp quan tâm hoặc bất cứ điều gì từ cam kết trước đó. Bạn hoàn toàn có thể loại bỏ các tệp trong "dự án của tôi - sao chép", nếu bạn đã quyết định công việc mới sẽ không đi đến đâu ...

Điều rõ ràng nếu bạn muốn tiếp tục với trạng thái của dự án mà không thực sự loại bỏ công việc vì cam kết đã lấy này là đổi tên thư mục của bạn một lần nữa: Xóa dự án có chứa cam kết đã lấy (hoặc đặt tên tạm thời) và đổi tên của bạn " dự án của tôi - sao chép "thư mục trở lại" dự án của tôi ". Sau đó, có thể làm một cam kết khá sớm.

Git là một sáng tạo tuyệt vời nhưng bạn không thể "nhặt nó lên": cũng là những người cố gắng giải thích nó quá thường xuyên giả định kiến ​​thức trước về các Hệ thống kiểm soát phiên bản khác của VCS và đi sâu quá sâu quá sớm và thực hiện các tội ác khác, như sử dụng các thuật ngữ có thể hoán đổi cho nhau để "kiểm tra" - theo những cách đôi khi xuất hiện gần như được tính toán để gây nhầm lẫn cho người mới bắt đầu.

Để giảm bớt căng thẳng, bạn phải đọc một cuốn sách về Git - Tôi khuyên bạn nên "Kiểm soát phiên bản với Git" . Và nếu bạn có thể tin tưởng tôi (hay đúng hơn là vết sẹo của tôi) khi tôi nói "phải", thì bạn cũng có thể làm điều đóNOW. Phần lớn sự phức tạp của Git đến từ sự phân nhánh và sau đó được làm lại. Nhưng từ câu hỏi của bạn có không có lý do tại sao mọi người nên làm mờ mắt bạn với khoa học .

Đặc biệt, nếu, ví dụ, đây là một tình huống tuyệt vọng và bạn là người mới với Git!

PS: Một suy nghĩ khác: (bây giờ) thực sự khá đơn giản để giữ kho Git ("repo") trong một thư mục khác với thư mục có các tệp đang hoạt động. Điều này có nghĩa là bạn sẽ không phải sao chép toàn bộ kho Git bằng giải pháp nhanh & bẩn ở trên. Xem câu trả lời của Fasher bằng cách sử dụng --separate-git-dir tại đây . Được cảnh báo , mặc dù: Nếu bạn có kho lưu trữ "thư mục riêng" mà bạn không sao chép và bạn thực hiện đặt lại cứng, tất cả các phiên bản sau cam kết đặt lại sẽ bị mất vĩnh viễn, trừ khi bạn có , như bạn hoàn toàn nên, thường xuyên sao lưu kho lưu trữ của mình, tốt nhất là lên đám mây (ví dụ Google Drive ) trong số những nơi khác.

13
mike rodent

Hãy thử đặt lại cam kết mong muốn -

git reset <COMMIT_ID>

(để kiểm tra Commit_ID sử dụng git log)

Điều này sẽ thiết lập lại tất cả các tập tin thay đổi về trạng thái chưa thêm.

Bây giờ bạn có thể checkout tất cả các tệp chưa được thêm bằng cách

git checkout .

Kiểm tra git log để xác minh thay đổi của bạn.

CẬP NHẬT

Nếu bạn có một và chỉ cam kết trong repo của bạn, hãy thử

git update-ref -d HEAD

13
optimistanoop

Chú ý! Lệnh này có thể gây mất lịch sử cam kết, nếu người dùng đặt nhầm cam kết. Luôn luôn có thêm bản sao lưu git của bạn một số nơi khác chỉ trong trường hợp nếu bạn làm sai, hơn là bạn an toàn hơn một chút. :)

Tôi đã có vấn đề tương tự và muốn trở lại Cam kết trước đó. Trong trường hợp của tôi, tôi không được khuyến khích giữ cam kết mới hơn do đó tôi đã sử dụng Hard.

Đây là cách tôi đã làm nó:

git reset --hard CommitId && git clean -f

Điều này sẽ hoàn nguyên trên kho lưu trữ cục bộ, tại đây sau khi sử dụng git Push -f sẽ cập nhật kho lưu trữ từ xa.

git Push -f
11

Khi các cam kết của bạn được đẩy từ xa, bạn cần xóa chúng. Hãy để tôi giả sử chi nhánh của bạn đang phát triển và nó được đẩy qua Origin.

Trước tiên bạn cần xóa phát triển khỏi Origin:

git Push Origin :develop (note the colon)

Sau đó, bạn cần phát triển đến trạng thái bạn muốn, hãy để tôi giả sử hàm băm cam kết là EFGHIJK:

git reset --hard EFGHIJK

Cuối cùng, Push phát triển lại:

git Push Origin develop
11
George Ninan

Trên GitKraken bạn có thể làm điều này:

  1. Nhấp chuột phải vào cam kết mà bạn muốn đặt lại, chọn: Đặt lại cho cam kết này/Cứng:

 enter image description here

  1. Nhấp chuột phải vào cam kết một lần nữa, chọn: Tên chi nhánh hiện tại/Đẩy:

 enter image description here

  1. Nhấp vào Đẩy mạnh:

 enter image description here

Quan sát. : Bạn cần cẩn thận vì tất cả lịch sử cam kết sau khi thiết lập lại cứng bị mất và hành động này là không thể đảo ngược. Bạn cần chắc chắn những gì bạn làm.

10
Ângelo Polotto

Nếu bạn muốn sửa một số lỗi trong lần xác nhận cuối cùng, một sự thay thế tốt sẽ là sử dụng lệnh git commit --amend . Nếu cam kết cuối cùng không được chỉ ra bởi bất kỳ tham chiếu nào, thì điều này sẽ thực hiện thủ thuật, vì nó tạo ra một cam kết có cùng cha mẹ với cam kết cuối cùng. Nếu không có tham chiếu đến lần xác nhận cuối cùng, đơn giản là nó sẽ bị loại bỏ và cam kết này sẽ là lần cam kết cuối cùng. Đây là một cách tốt để sửa lỗi cam kết mà không hoàn nguyên các cam kết. Tuy nhiên nó có những hạn chế riêng của nó.

10
Upul Doluweera

Đầu tiên, lấy chuỗi xác định cam kết trong một số ngày, thực hiện:

git rev-list -n 1 --before="2009-07-27 13:37" Origin/master

nó in định danh cam kết, lấy chuỗi (ví dụ XXXX) và làm:

git checkout XXXX
9
Luca C.

Đối với rollback (hoặc để hoàn nguyên):

  1. git Revert --no-commit "commit-code-to-remove" HEAD (ví dụ: git Revert --no-commit d57a39d HEAD)
  2. cam kết
  3. đẩy git

Hãy thử ở trên hai bước và nếu bạn thấy đây là những gì bạn muốn thì hãy git Push.

Nếu bạn tìm thấy một cái gì đó sai làm:

git hoàn nguyên --abort

9
Jagraj Singh

Nó có thể được thực hiện dễ dàng hơn nhiều với SourceTree . Chỉ cần nhấp chuột phải vào cam kết bạn đang tìm kiếm và chọn 'Thanh toán' từ menu.

 enter image description here

8
Marcin Szymczak

Một giải pháp đơn giản nhất khác; bạn phải thay đổi chi nhánh để làm điều này, nhưng sau đó bạn có thể chạy:

git branch -f <<branchname>> 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
8
Aif

Tôi không thể hoàn nguyên thủ công vì một số lý do vì vậy đây là cách tôi kết thúc việc đó.

  1. Kiểm tra chi nhánh tôi muốn có, sao chép nó.
  2. Kiểm tra chi nhánh mới nhất.
  3. Sao chép nội dung từ chi nhánh mà tôi muốn vào thư mục của chi nhánh mới nhất ghi đè lên các thay đổi và cam kết điều đó.
7
Demodave
git reflog

Chọn số lượng TRỰC TIẾP của git reflog, nơi bạn muốn hoàn nguyên và thực hiện (ví dụ này tôi chọn 12):

git reset [email protected]{12} --hard
7
Sérgio

Cách ít phức tạp nhất để hoàn nguyên một nhánh thành bất kỳ cam kết cụ thể nào mà bạn không thể thay đổi lịch sử mà tôi đã tìm thấy là:

  1. kiểm tra cam kết hoặc chi nhánh bạn muốn hoàn nguyên.
  2. Chỉnh sửa .git/HEAD và thay đổi ref thành nhánh mà bạn sẽ hoàn nguyên.

Nhu la:

echo 'ref: refs/heads/example' > .git/HEAD

Nếu sau đó bạn thực hiện trạng thái git, bạn sẽ thấy tất cả các thay đổi giữa nhánh bạn đang ở và nhánh bạn muốn hoàn nguyên.

Nếu mọi thứ có vẻ tốt, bạn có thể cam kết. Bạn cũng có thể sử dụng git diff Revert..example để đảm bảo rằng nó giống nhau.

6
jgmjgm

Nếu bạn muốn tạm thời hoàn nguyên các thay đổi vì

  • ai đó đã cam kết mã rằng nó phá vỡ bản dựng hoặc phá vỡ chức năng bạn đang làm việc

Bạn có thể tìm kiếm cam kết làm việc cuối cùng bằng cách sử dụng nhật ký git rồi chạy

git rebase --onto <commitId>

Khi chi nhánh từ xa hoạt động trở lại, bạn có thể

git pull --rebase

Phương pháp này tốt hơn kiểm tra git cho những thay đổi tạm thời, bởi vì bạn không ở trong trạng thái tách rời.

5
joseph

Đặt lại các thay đổi và cam kết theo giai đoạn

Lệnh git reset cho phép bạn thay đổi CHÍNH- cam kết mới nhất của cây làm việc của bạn thành - của kho lưu trữ của bạn. Nó sửa đổi khu vực tổ chức hoặc khu vực tổ chức và cây làm việc. Khả năng tạo thủ công của Git chính xác như bạn muốn có nghĩa là đôi khi bạn cần hoàn tác các thay đổi đối với các thay đổi bạn đã thực hiện với git add. Bạn có thể làm điều đó bằng cách gọi git reset HEAD <file to change>. Bạn có hai lựa chọn để loại bỏ hoàn toàn các thay đổi. git checkout HEAD <file(s) or path(s)> là một cách nhanh chóng để hoàn tác các thay đổi đối với khu vực tổ chức và cây làm việc của bạn. Tuy nhiên, hãy cẩn thận với lệnh này vì nó loại bỏ tất cả các thay đổi đối với cây làm việc của bạn. Git không biết về những thay đổi đó vì chúng chưa bao giờ được cam kết. Không có cách nào để lấy lại những thay đổi đó khi bạn chạy lệnh này. Một lệnh khác theo ý của bạn là git reset --hard. Nó cũng có sức tàn phá không kém đối với cây làm việc của bạn - mọi thay đổi không được cam kết hoặc thay đổi theo giai đoạn sẽ bị mất sau khi chạy nó. Chạy git reset -hard HEAD thực hiện tương tự như kiểm tra git HEAD. nó chỉ không yêu cầu tệp hoặc đường dẫn để hoạt động. Bạn có thể sử dụng --soft với git reset. Nó đặt lại kho lưu trữ theo cam kết bạn chỉ định và thực hiện tất cả các thay đổi đó. Mọi thay đổi bạn đã dàn dựng đều không bị ảnh hưởng, cũng không phải là những thay đổi trong cây làm việc của bạn. Cuối cùng, bạn có thể sử dụng --mixed để đặt lại cây làm việc mà không cần thay đổi bất kỳ thay đổi nào.

Cam kết hoàn lại

Đôi khi chúng ta phạm sai lầm. Một cam kết không được chia sẻ sẽ bị đẩy vào kho lưu trữ công khai, một cam kết có lỗi không thể sửa được và cần được hoàn tác hoặc có thể bạn không cần mã đó nữa. gọi cho git revert. Lệnh git revert thực hiện đúng những gì bạn mong đợi. Nó hoàn nguyên một cam kết duy nhất bằng cách áp dụng một cam kết ngược lại cho lịch sử. Đôi khi bạn cần hoàn nguyên một số cam kết để hoàn tác một thay đổi. Bạn có thể sử dụng -no-commit hoặc bạn có thể sử dụng -n để nói với Git để thực hiện hoàn nguyên nhưng không bao giờ thực hiện thay đổi. Điều này cho phép bạn kết hợp tất cả các cam kết hoàn nguyên thành một cam kết, rất hữu ích nếu bạn cần hoàn nguyên một tính năng kéo dài một số cam kết. Hãy chắc chắn rằng bạn hoàn nguyên các cam kết theo thứ tự ngược lại - cam kết mới nhất trước tiên. Mặt khác, bạn có thể nhầm lẫn Git bằng cách cố gắng hoàn nguyên mã chưa tồn tại.

2
SAIguru011