git chọn lọc hoàn nguyên các thay đổi cục bộ từ một tệp


149

Trong git repo của tôi đang theo dõi một repo svn, tôi đã thực hiện một số chỉnh sửa cho một tệp.

Bây giờ tôi muốn hoàn nguyên những thay đổi đó (như svn Revert), nhưng chỉ một phần của tệp.

Tôi muốn có thể xem các khác biệt trên tệp, loại bỏ (hoàn nguyên) các thay đổi mà tôi không muốn và giữ lại các thay đổi tôi muốn.

các

git add -i 

lệnh dường như có một tùy chọn để làm điều đó nhưng tôi chưa muốn thực hiện điều này.

Câu trả lời:


91

Bạn có thể làm điều đó trực tiếp với git checkout -p. Xem câu trả lời của Daniel Stutzbach dưới đây.


Câu trả lời cũ (trước khi checkout -pđược giới thiệu):

Bạn có thể làm như thế này:

git add -i

(chọn những người bạn muốn giữ)

git commit -m "tmp"

Bây giờ bạn có một cam kết chỉ với những thay đổi bạn muốn giữ và phần còn lại không được thực hiện.

git reset --hard HEAD

Tại thời điểm này, các thay đổi không được cam kết đã bị loại bỏ, vì vậy bạn có một thư mục hoạt động sạch sẽ, với các thay đổi bạn muốn giữ cam kết lên hàng đầu.

git reset --mixed HEAD^

Điều này loại bỏ cam kết cuối cùng ('tmp'), nhưng giữ cho các sửa đổi trong thư mục làm việc của bạn, không được thực hiện.

EDIT: thay thế --softbằng --mixed, để làm sạch khu vực tổ chức.


Điều này sẽ cam kết những thay đổi mà tôi muốn giữ phải không? Tôi không muốn thực hiện những thay đổi đó. mm có lẽ tôi đang thực hiện cam kết quá nghiêm túc. Có lẽ tôi nên thư giãn ngay bây giờ vì tất cả nằm trong một repo địa phương. btw git reset --soft Head ^ làm gì?
Pradeep

"git reset --soft HEAD ^" hoàn tác một cam kết theo nghĩa là nó sẽ giữ thư mục và chỉ mục hoạt động như cũ, và di chuyển lại một nhánh hiện tại.
Jakub Narębski

Cảm ơn Jakub. Tại sao một thiết lập lại mềm cho đầu - 1 được yêu cầu ở đây? cam kết một phần và thiết lập lại cứng có đủ không để giữ một số thay đổi và loại bỏ những thay đổi khác?
Pradeep

1
Câu trả lời của Daniel dưới đây rất đơn giản và có vẻ là cách đúng đắn để làm điều đó.
Umang

309

Tôi tin rằng bạn có thể làm điều đó đơn giản nhất với:

git checkout -p <optional filename(s)>

Từ trang hướng dẫn:

   −p, −−patch
       Interactively select hunks in the difference between the <tree−ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree−ish> was specified, the index).
       This means that you can use git checkout −p to selectively discard
       edits from your current working tree.

1
Ngoài ra, nếu bạn không muốn thực hiện việc này một cách có chọn lọc, bạn có thể sử dụng "kiểm tra git - <file> ..." để loại bỏ các thay đổi.
db42

Nó có đối phó với các thư mục?
bbum

1
Điều này dường như thất bại rất nhiều đối với tôi khi loại bỏ các thay đổi ("error: patch fail <file>", "error: <file> patch không áp dụng"). Thật kỳ lạ, tôi sẽ nhận được những lỗi đó khi sử dụng atùy chọn trong chế độ vá để loại bỏ toàn bộ tệp, nhưng vẫn git checkout -- <file>hoạt động như mong đợi. Có ai biết tại sao không?
chrnola

Tôi đã gặp lỗi đó một vài lần nếu tệp đã được vá và vì vậy bản vá tương tác đã lỗi thời với các bản vá được áp dụng của tệp hiện tại. Nó đã xảy ra khi sử dụng một công cụ gui như cây nguồn nếu tôi vô tình vứt bỏ một hunk hai lần. Lần thứ hai sẽ tạo ra lỗi đó.
phyatt

3

Bạn có thể chạy git difftrên các tập tin, tiết kiệm các diff kết quả, chỉnh sửa nó để loại bỏ những thay đổi bạn làm muốn lưu, sau đó chạy nó thông qua patch -Rđể hoàn tác các diffs còn lại.

git diff file.txt> patch.tmp
# chỉnh sửa patch.tmp để xóa các khối mà bạn muốn giữ
bản vá -R <patch.tmp

Tôi đã có 2 hunk trong tập tin vá của tôi và loại bỏ một. Không chắc chắn lý do là gì nhưng bản vá -R tiếp tục bị từ chối với điều này.
Pradeep

2
Bạn đề cập trong một bình luận khác git diffcho thấy toàn bộ tập tin như đã thay đổi. Điều này thường xảy ra khi bạn đã lưu tệp bằng các kết thúc dòng khác nhau so với trước đây. Điều này cũng sẽ patchtừ chối các tập tin vá. Nghe có vẻ như những gì có thể đã xảy ra?
Greg Hewgill

bạn đúng rồi. các kết thúc dòng đang được bật bất cứ khi nào tôi sử dụng lệnh vá. Tôi đang trên cửa sổ và sử dụng kem / vim. Tôi cần phải sắp xếp cái này trước.
Pradeep

Tôi không thể giải quyết vấn đề với bản vá trên windows. Mặc dù tôi chắc chắn rằng công việc này tôi thích sử dụng công thức của Paolo. Đối với tình yêu của các lệnh tương tác để làm việc với các diff sử dụng git add -i.
Pradeep

3

Hình như bạn muốn

 git revert --no-commit $REVSISON 

Sau đó bạn có thể sử dụng

 git diff --cached

để xem những thay đổi nào sẽ được thực hiện trước khi cam kết (vì hoàn nguyên chỉ là một cam kết theo hướng chuyển tiếp sao chép nghịch đảo của một thay đổi trong quá khứ)

Nếu bạn có kho lưu trữ Git thuần túy, bạn có thể, tùy thuộc vào mục tiêu của mình, sử dụng rebase tương tác ( git rebase -i) để quay lại cam kết mà bạn không thích và chỉnh sửa cam kết hồi quy để những thay đổi bạn không muốn xảy ra , nhưng điều đó thường chỉ dành cho nếu bạn BIẾT bạn sẽ không bao giờ muốn gặp lại nó.


Tôi đã hoàn nguyên như bạn đã đề cập đến một phiên bản trước (có đúng không?) Và bây giờ git diff chỉ hiển thị toàn bộ tệp như đã thay đổi. Nó được cho là để hiển thị các chỉnh sửa mà tôi đã thực hiện?
Pradeep

1

Đọc lại câu hỏi, có vẻ như bạn muốn hoàn nguyên các thay đổi trong cây làm việc của bạn và không phải là những thay đổi đã được cam kết trước đó, nhưng một số câu trả lời khác làm cho việc đọc của tôi có thể sai. Bạn có thể làm rõ?

Nếu các thay đổi chỉ có trong bản sao làm việc của bạn thì cách dễ nhất để thực hiện việc này là thực hiện các thay đổi bạn muốn thực hiện:

git add -i <file>

Sau đó, vứt bỏ những thay đổi mà bạn không muốn giữ bằng cách kiểm tra phiên bản chỉ mục:

git checkout -- <file>

Sau đó, bỏ qua các thay đổi nếu bạn chưa muốn chúng được dàn dựng:

git reset -- <file>

Công thức này chỉ hoàn nguyên các thay đổi đã chọn đối với tệp (hoặc tệp mà bạn chỉ định) và không tạo ra bất kỳ cam kết tạm thời nào sau đó cần hoàn nguyên.

Nếu bạn muốn chỉ áp dụng có chọn lọc một số thay đổi được thực hiện trong các lần xác nhận trước đó thì trước tiên bạn có thể đặt lại tệp về trạng thái đã cam kết trước đó:

git reset <commit_before_first_unwanted_change> -- <file>

Sau đó, bạn có thể làm theo công thức trước đó git add -i <file>để thực hiện các thay đổi mà bạn muốn giữ, git checkout -- <file>để loại bỏ các thay đổi không mong muốn và git reset -- <file>' không thể thay đổi ' các thay đổi.


0

Các tùy chọn dòng lệnh được mô tả trong các câu trả lời ở đây rất tiện lợi khi tệp nằm trên máy chủ mà tôi đang truy cập thông qua thiết bị đầu cuối ssh. Tuy nhiên, khi tệp nằm trong máy cục bộ của tôi, tôi thích cách sau:

Mở tệp trong trình soạn thảo netbeans (đi kèm với hỗ trợ git). Netbeans đặt các dấu đỏ / xanh / xanh dương ở các số dòng để chỉ ra nơi các công cụ đã bị xóa / thêm / sửa đổi (tương ứng).

Nhấp chuột phải vào bất kỳ dấu nào trong số này cung cấp cho bạn một tùy chọn để hoàn tác thay đổi đó. Ngoài ra, bạn có thể nhấp chuột phải vào các dấu đỏ và xanh để thấy phiên bản cũ trong cửa sổ bật lên.

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.