Làm cách nào để xóa các cam kết git chưa được chỉnh sửa?


948

Tôi vô tình phạm phải sai chi nhánh. Làm cách nào để xóa cam kết đó?

Câu trả lời:


1811

Xóa các cam kết gần đây nhất, giữ cho công việc bạn đã thực hiện:

git reset --soft HEAD~1

Xóa các cam kết gần đây nhất, phá hủy công việc bạn đã thực hiện:

git reset --hard HEAD~1

13
hãy chắc chắn rằng CHÍNH đang chỉ vào chi nhánh .. (kiểm tra trước)
Frank Schwieterman

128
Và hãy chắc chắn rằng CHÍNH ~ 1 là cam kết ... Bạn cũng có thể làmgit reset --hard origin
Daenyth

13
git remoteDanh sách suy nghĩ nguồn gốc cho tôi, git reset --hard originnói fatal: ambiguous argument 'origin': unknown revision or path not in the working tree.. Tại sao?
trss

7
Điều này thật tuyệt. Chỉ cứu mạng tôi.
NinjaBoy

2
git reset HEAD~1cũng sẽ giữ tất cả các thay đổi của bạn nhưng sẽ để lại cho bạn một chỉ mục trống thay vì giữ mọi thứ (như --softtùy chọn sẽ).
Holloway

139

Tôi tự hỏi tại sao câu trả lời tốt nhất mà tôi tìm thấy chỉ có trong các bình luận! ( bởi Daenyth với 86 phiếu bầu )

git reset --hard origin

Lệnh này sẽ đồng bộ hóa kho lưu trữ cục bộ với kho lưu trữ từ xa để loại bỏ mọi thay đổi bạn đã thực hiện trên cục bộ của mình. Bạn cũng có thể làm như sau để lấy chi nhánh chính xác mà bạn có trong nguồn gốc.

git reset --hard origin/<branch>

16
Cảm ơn vì điều này, mở rộng lời giải thích một chút: cho một chi nhánh cụ thể:git reset --hard origin/<branch>
rõ ràng

4
Hoặc git reset --soft origin/<branch>, nếu bạn muốn thoát khỏi cam kết nhưng vẫn giữ công việc địa phương.
Riverhorse

1
Tôi nhận được fatal: ambiguous argument 'origin': unknown revision or path not in the working tree., bạn cần chỉ định chi nhánh như:git reset --hard origin/feature/my-cool-stuff
Kip

Xuất sắc! Điều này thực sự hoạt động, không giống như câu trả lời "được chấp nhận" chỉ làm mất đầu và khiến bạn bị treo.
mae

55

Đừng xóa nó: chỉ một lần cam kết git cherry-picklà đủ.

Nhưng nếu bạn có một vài cam kết trên nhánh sai, đó là nơi git rebase --ontotỏa sáng:

Giả sử bạn có cái này:

 x--x--x--x <-- master
           \
            -y--y--m--m <- y branch, with commits which should have been on master

, sau đó bạn có thể đánh dấu mastervà di chuyển nó đến nơi bạn muốn:

 git checkout master
 git branch tmp
 git checkout y
 git branch -f master

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- y branch, master branch

, đặt lại nhánh y nơi cần có:

 git checkout y
 git reset --hard HEAD~2 # ~1 in your case, 
                         # or ~n, n = number of commits to cancel

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- master branch
                ^
                |
                -- y branch

và cuối cùng di chuyển các cam kết của bạn (áp dụng lại chúng, thực hiện các cam kết mới)

 git rebase --onto tmp y master
 git branch -D tmp


 x--x--x--x--m'--m' <-- master
           \
            -y--y <- y branch

Thật không may, đó không phải là câu hỏi.
KatariaA

1
@KatariaA Đó là một cách thay thế hợp lệ để xóa các cam kết được thực hiện trên nhánh sai và sẽ giúp những người khác trong tình huống tương tự (cam kết tốt được thực hiện trên nhánh sai).
VonC

14

Thực hiện git rebase -i FAR_ENOUGH_BACKvà thả dòng cho cam kết bạn không muốn.


6

Nếu bạn muốn chuyển cam kết đó sang chi nhánh khác, hãy lấy SHA của cam kết đó trong câu hỏi

git rev-parse HEAD

Sau đó chuyển đổi chi nhánh hiện tại

git checkout other-branch

cherry-pickcam kếtother-branch

git cherry-pick <sha-of-the-commit>

Từ kinh nghiệm của tôi, điều này không hoàn tác cam kết từ chi nhánh ban đầu, do đó cần phải có git reset --hard HEAD~1sau đó. Tôi nghĩ rằng sử dụng reset --softsau đó chuyển đổi chi nhánh và cam kết một lần nữa sẽ tiết kiệm thêm công việc. Sau đó, một lần nữa tôi đã sử dụng SourceTree để thực hiện hầu hết các công cụ cơ bản của mình, chỉ sử dụng dòng lệnh này với lỗi này sau lỗi của tôi.
jusopi

3

Để bạn tham khảo, tôi tin rằng bạn có thể "cắt cứng" cam kết ra khỏi chi nhánh hiện tại của mình không chỉ với git reset --hard, mà còn bằng lệnh sau:

git checkout -B <branch-name> <SHA>

Thực tế, nếu bạn không quan tâm đến việc kiểm tra, bạn có thể đặt chi nhánh thành bất cứ điều gì bạn muốn với:

git branch -f <branch-name> <SHA>

Ví dụ, đây sẽ là một cách lập trình để loại bỏ các xác nhận khỏi một nhánh để sao chép các xác nhận mới vào nó (sử dụng rebase).

Giả sử bạn có một nhánh bị ngắt kết nối với chủ vì bạn đã lấy nguồn từ một số vị trí khác và đổ nó vào nhánh.

Bây giờ bạn có một chi nhánh mà bạn đã áp dụng các thay đổi, hãy gọi nó là "chủ đề".

Bây giờ bạn sẽ tạo một bản sao của nhánh chủ đề của mình và sau đó khởi động lại nó vào bãi chứa mã nguồn đang nằm trong nhánh "dump":

git branch topic_duplicate topic
git rebase --onto dump master topic_duplicate

Bây giờ các thay đổi của bạn được áp dụng lại trong nhánh topic_d repeatate dựa trên điểm bắt đầu của "kết xuất" nhưng chỉ các cam kết đã xảy ra kể từ "chính". Vì vậy, những thay đổi của bạn kể từ chủ hiện được áp dụng lại ở đầu "kết xuất" nhưng kết quả cuối cùng lại xuất hiện trong "topic_d repeatate".

Sau đó, bạn có thể thay thế "kết xuất" bằng "topic_d repeatate" bằng cách thực hiện:

git branch -f dump topic_duplicate
git branch -D topic_duplicate

Hoặc với

git branch -M topic_duplicate dump

Hoặc chỉ bằng cách loại bỏ bãi rác

git branch -D dump

Có lẽ bạn cũng có thể chọn cherry sau khi xóa "topic_d repeatate" hiện tại.

Điều tôi đang cố gắng nói là nếu bạn muốn cập nhật nhánh "trùng lặp" hiện tại dựa trên một tổ tiên khác, trước tiên bạn phải xóa các cam kết "được chọn" trước đó bằng cách thực hiện git reset --hard <last-commit-to-retain> hoặc git branch -f topic_duplicate <last-commit-to-retain>sau đó sao chép các cam kết khác (từ chính chi nhánh chủ đề) bằng cách nổi loạn hoặc chọn anh đào.

Rebasing chỉ hoạt động trên một nhánh đã có các cam kết, vì vậy bạn cần sao chép nhánh chủ đề của mình mỗi lần bạn muốn làm điều đó.

Cherrypicking dễ dàng hơn nhiều:

git cherry-pick master..topic

Vì vậy, toàn bộ chuỗi sẽ đi xuống:

git reset --hard <latest-commit-to-keep>
git cherry-pick master..topic

Khi chi nhánh trùng lặp chủ đề của bạn đã được kiểm tra. Điều đó sẽ loại bỏ các cam kết được chọn trước đó khỏi bản sao hiện tại và chỉ cần áp dụng lại tất cả các thay đổi xảy ra trong "chủ đề" trên "bãi rác" hiện tại của bạn (tổ tiên khác). Có vẻ như một cách hợp lý thuận tiện để dựa trên sự phát triển của bạn dựa trên tổng thể ngược dòng "thực" trong khi sử dụng một chủ "hạ lưu" khác để kiểm tra xem các thay đổi cục bộ của bạn có còn áp dụng cho điều đó hay không. Ngoài ra, bạn có thể tạo ra một khác biệt và sau đó áp dụng nó bên ngoài bất kỳ cây nguồn Git nào. Nhưng theo cách này, bạn có thể giữ một phiên bản cập nhật (đã vá) được cập nhật dựa trên phiên bản phân phối của bạn trong khi sự phát triển thực tế của bạn chống lại chủ nhân ngược dòng thực sự.

Vì vậy, chỉ để chứng minh:

  • thiết lập lại sẽ khiến chi nhánh của bạn trỏ đến một cam kết khác (- cũng kiểm tra các cam kết trước đó, --soft giữ các tệp được thêm vào trong chỉ mục (sẽ được cam kết nếu bạn cam kết lại) và mặc định (- đã trộn) sẽ không kiểm tra cam kết trước đó (xóa các thay đổi cục bộ của bạn) nhưng nó sẽ xóa chỉ mục (chưa có gì được thêm cho cam kết)
  • bạn chỉ có thể buộc một nhánh chỉ vào một cam kết khác
  • bạn có thể làm như vậy trong khi ngay lập tức kiểm tra cam kết đó
  • rebasing hoạt động trên cam kết hiện tại trong chi nhánh hiện tại của bạn
  • hái anh đào có nghĩa là sao chép từ một chi nhánh khác

Hy vọng điều này sẽ giúp được ai đó. Tôi có ý định viết lại cái này, nhưng giờ tôi không thể quản lý được. Trân trọng.


0

Theo lệnh đã làm việc cho tôi, tất cả các thay đổi đã cam kết cục bộ bị loại bỏ và cục bộ được đặt lại giống như nhánh gốc / nhánh chính từ xa.

thiết lập lại git - nguồn gốc

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.