Câu hỏi Xóa các tệp khỏi Git commit


Tôi đang sử dụng Git và tôi đã cam kết vài tệp bằng

git commit -a

Sau đó, tôi thấy rằng một tập tin đã nhầm lẫn đã được thêm vào cam kết.

Làm cách nào để xóa tệp khỏi lần commit cuối cùng?


1094
2017-09-18 16:59


gốc


Liên kết này là hoàn hảo cho câu hỏi của bạn: stackoverflow.com/questions/307828/… - b3h3m0th
@CharlesB: vâng, đây là lần commit cuối cùng của tôi - Mojoy
bạn đã đẩy cam kết vào máy chủ chưa? - Paritosh Singh
Tôi chỉ làm điều đó bằng cách sử dụng: git reset filepath - felipekm


Các câu trả lời:


Tôi nghĩ rằng câu trả lời khác ở đây là sai, bởi vì đây là một câu hỏi di chuyển các tập tin nhầm lẫn cam kết trở lại khu vực dàn dựng từ cam kết trước đó, mà không hủy bỏ những thay đổi được thực hiện cho họ. Điều này có thể được thực hiện như Paritosh Singh đề nghị:

git reset --soft HEAD^ 

hoặc là

git reset --soft HEAD~1

Sau đó, đặt lại các tệp không mong muốn để chúng thoát khỏi cam kết:

git reset HEAD path/to/unwanted_file

Bây giờ cam kết một lần nữa, bạn thậm chí có thể tái sử dụng cùng một thông báo cam kết:

git commit -c ORIG_HEAD  

2104
2018-03-10 10:56



Cám ơn vì cái này. Điều đáng nói là nếu bạn đã đẩy cam kết trước đó (sai) của mình, và bây giờ hãy thử git push sửa chữa của bạn lên đến repo của bạn, nó sẽ khiếu nại Updates were rejected because the tip of your current branch is behind its remote counterpart.. Nếu bạn chắc chắn rằng bạn muốn đẩy chúng (ví dụ: đó là ngã ba của bạn) thì bạn có thể sử dụng -f tùy chọn ép buộc, ví dụ: git push origin master -f. (Đừng làm điều này với một repo ngược dòng mà những người khác đang tìm nạp) - andy magoon
git reset --soft HEAD^ là hoạt động hoàn tác phổ biến nhất của tôi - funroll
@PabloFernandez, trước hết, câu trả lời được chấp nhận có thể là những gì OP đang tìm kiếm (Ngoài ra, nó đã được đăng tháng trước đó). Thứ hai, câu trả lời được chấp nhận luôn ở trên đầu bất kể số phiếu bầu lên. - MITjanitor
@PabloFernandez ở đầu tất cả các câu trả lời là ba tab cho phép bạn kiểm soát thứ tự các câu trả lời: hoạt động, lâu đời nhất và phiếu bầu. Đoán của tôi là của bạn được thiết lập để lâu đời nhất. Chuyển nó sang phiếu bầu mặc dù câu trả lời được chấp nhận sẽ vẫn ở trên cùng, câu trả lời này sẽ là câu trả lời thứ hai. - ahsteele
Tôi biết điều này nhiều về git reset nhưng muốn có một cách để ảnh hưởng đến cam kết hiện tại "tại chỗ". Tôi vừa học về git commit -C. Vì vậy, đối với tôi, những gì tôi muốn là công thức chính xác của bạn với một bước nữa, "cam kết mới một lần nữa" đánh vần như git commit -C [hash of original HEAD commit from first step]. - metamatt


CHÚ Ý! Nếu bạn chỉ muốn xóa tệp khỏi cam kết trước đó của mình và giữ nó trên đĩa, đọc câu trả lời của juzzlin ngay phía trên.

Nếu đây là lần commit cuối cùng của bạn và bạn muốn xóa hoàn toàn tệp từ cục bộ và kho lưu trữ từ xa của bạn, bạn có thể:

  1. xóa tệp git rm <file>
  2. cam kết với cờ sửa đổi: git commit --amend

Cờ sửa đổi yêu cầu git cam kết lần nữa, nhưng "hợp nhất" (không phải trong ý nghĩa kết hợp hai nhánh) cam kết này với lần commit cuối cùng.

Như đã nêu trong các ý kiến, sử dụng git rm ở đây giống như sử dụng rm lệnh của chính nó!


218
2017-09-18 17:22



bạn cũng có thể dùng git rm --cached để giữ các tập tin trên đĩa - Arkadiy Kukarkin
Cảnh báo với những người đang duyệt câu trả lời này: đảm bảo rằng bạn muốn XÓA tệp (như đã biến mất), không chỉ xóa nó khỏi danh sách Cam kết. - Scott Biggs
Để thêm vào những gì người khác nói (và để làm cho nó dễ dàng hơn để nhớ không làm điều này trừ khi bạn thực sự muốn): Các rm bên trong git chỉ huy Là làm gì rm chính nó! - yo'
@ CharlesB Bạn có thể vui lòng thêm ghi chú từ bình luận của Arkadiy Kukarkin vào câu trả lời của bạn để cho nó hiển thị rõ hơn không? - mopo922
Lưu ý rằng các tập tin vẫn có thể được phục hồi, trong trường hợp bạn thay đổi ý định của bạn, các cam kết trước git commit --amend vẫn ở đó và có thể tìm thấy ví dụ với git reflog. Vì vậy, nó không phải là xấu như các ý kiến ​​khác đề nghị. - Steohan


Các câu trả lời hiện có tất cả đang nói về việc xóa các tệp không mong muốn khỏi Cuối cùng cam kết.

Nếu bạn muốn xóa các tệp không mong muốn khỏi  cam kết (thậm chí bị đẩy) và không muốn tạo một cam kết mới, điều đó là không cần thiết, vì hành động:

1.

Tìm cam kết mà bạn muốn tệp phù hợp.

git checkout <commit_id> <path_to_file>

bạn có thể thực hiện việc này nhiều lần nếu bạn muốn xóa nhiều tệp.

2.

git commit -am "remove unwanted files"

3.

Tìm commit_id của cam kết trên đó các tệp đã được thêm nhầm, giả sử "35c23c2" ở đây

git rebase 35c23c2~1 -i  // notice: "~1" is necessary

Lệnh này sẽ mở trình chỉnh sửa theo cài đặt của bạn. Cái mặc định là vim.

Di chuyển cam kết cuối cùng, mà nên là "loại bỏ các tập tin không mong muốn", đến dòng tiếp theo của cam kết không chính xác ("35c23c2" trong trường hợp của chúng tôi), và thiết lập lệnh như fixup:

pick 35c23c2 the first commit
fixup 0d78b28 remove unwanted files

Bạn nên tốt sau khi lưu tập tin.

Kêt thuc :

git push -f

Nếu bạn không may nhận được xung đột, bạn phải giải quyết chúng theo cách thủ công.


107
2018-01-27 15:24



Làm điều này với nano là tuyệt vời! Ctrl + K, Ctrl + U, đặt một 'f', Ctrl + X, đặt 'y' và thì đấy! - sequielo
Nếu bạn thực sự muốn xóa các tệp khỏi repo (không phải hệ thống tệp), thay vì chỉ hoàn nguyên các tệp đó thành phiên bản trước, thì thay vì bước 1 git rm --cached <file(s)>. - waldyrious
Đợi bạn chỉ có thể di chuyển các cam kết xung quanh tệp tương tác-rebase theo ý muốn? - Dan Rosenstark
Bạn hoàn toàn có thể, nhưng bạn có thể (hoặc có thể không) bị xung đột. - Brian
Quá trình này có thể được thực hiện dễ dàng hơn một chút bằng cách thêm --fixup=35c23c2 đến git commit chỉ huy. Điều này sẽ thiết lập cam kết tự động như là một sửa chữa của các cam kết cần thiết và do đó bạn sẽ không cần phải xác định nó trong rebase. Ngoài ra, nếu bạn thêm --autosquash đến git rebase lệnh, git sẽ tự động di chuyển cam kết của bạn đến đúng vị trí, vì vậy bạn không cần phải làm bất cứ điều gì trong rebase tương tác - chỉ cần lưu kết quả (có nghĩa là bạn thậm chí không cần phải -i mặc dù tôi vẫn muốn sử dụng nó để đảm bảo mọi thứ trông như tôi mong đợi). - Guss


Khi câu trả lời được chấp nhận cho biết, bạn có thể làm điều này bằng cách đặt lại toàn bộ cam kết. Nhưng đây là một cách tiếp cận khá nặng tay.
Một cách sạch hơn để làm điều này là giữ cam kết và chỉ xóa các tệp đã thay đổi khỏi nó.

git reset HEAD^ -- path/to/file
git commit --amend --no-edit

Các git reset sẽ lấy tệp như trong cam kết trước đó và đặt nó trong chỉ mục. Tệp trong thư mục làm việc không bị ảnh hưởng.
Các git commit sau đó sẽ cam kết và nén chỉ mục vào cam kết hiện tại.

Điều này về cơ bản có phiên bản của tập tin đó là trong cam kết trước đó và thêm nó vào cam kết hiện tại. Điều này dẫn đến không có thay đổi ròng, và do đó, các tập tin có hiệu quả loại bỏ từ cam kết.


62
2018-02-25 00:06



Đây là một câu trả lời tốt hơn nhiều cho việc loại bỏ chỉ một tập tin duy nhất, mà không cần đại tu toàn bộ cam kết. - nimish
Điều này tốt hơn câu trả lời được chấp nhận - chet
Điều này hoàn toàn giống với câu trả lời này: D stackoverflow.com/a/27340569/1623984 - ThatsAMorais
@ThatsAMorais thực sự :-). Tôi tự hỏi nếu câu hỏi này đã được sáp nhập với một câu hỏi khác, và đó là lý do tại sao tôi không nhìn thấy nó. Hoặc có lẽ tôi chỉ mù. Dù là gì đi chăng nữa, tôi nghĩ tôi có khuynh hướng để nó dựa trên số phiếu bầu, dường như nó phổ biến hơn (có thể mọi người thích câu trả lời ngắn và trực tiếp). - Patrick
Bằng mọi cách bỏ nó đi! :) Chúng tôi rõ ràng đã có ý tưởng đúng, và mục đích là để giúp đỡ. Tôi nghĩ việc sáp nhập là một lý thuyết tốt. - ThatsAMorais


Nếu bạn chưa đẩy các thay đổi trên máy chủ, bạn có thể sử dụng

git reset --soft HEAD~1

Nó sẽ đặt lại tất cả các thay đổi và hoàn nguyên về một lần commit

Nếu bạn đã đẩy các thay đổi của mình, hãy làm theo các bước như được trả lời bởi @CharlesB


35
2017-09-18 18:28



-1 git reset loại bỏ những thay đổi đã xảy ra tập tin từ khu vực dàn dựng, ở đây thay đổi đã được cam kết - CharlesB
@CharlesB sry, chỉnh sửa các thay đổi. - Paritosh Singh
OK, nhưng tôi sẽ giữ nguyên ý kiến ​​của tôi vì nó không phải là những gì OP muốn :) xin lỗi - CharlesB
ok nó tốt cho tôi, nhưng tại sao đối thủ không muốn điều này. Vấn đề là gì? - Paritosh Singh
@Aris sử dụng <git diff --cached> để xem các thay đổi - Paritosh Singh


Loại bỏ các tập tin bằng cách sử dụng rm sẽ xóa nó!

Bạn luôn thêm commit vào git thay vì remove, vì vậy trong instance này trả về file về trạng thái trước khi commit đầu tiên (đây có thể là hành động delete 'rm' nếu file mới) và sau đó cam kết lại và tệp sẽ đi.

Để trả lại tệp về một số trạng thái trước đó:

    git checkout <commit_id> <path_to_file>

hoặc để trả lại trạng thái tại HEAD ở xa:

    git checkout origin/master <path_to_file>

sau đó sửa đổi các cam kết và bạn nên tìm tập tin đã biến mất khỏi danh sách (và không bị xóa khỏi đĩa của bạn!)


34
2018-01-28 14:00





git checkout HEAD~ path/to/file
git commit --amend

33
2017-08-23 19:01



Đây là cách tốt nhất để sửa đổi lần commit cuối cùng, cái chưa được đẩy. Điều này sẽ đặt lại các thay đổi trong một tệp, loại bỏ tệp đó một cách hiệu quả khỏi lần commit cuối cùng. - Alex Bravo


Sau đây sẽ chỉ unstage tập tin bạn dự định, đó là những gì OP hỏi.

git reset HEAD^ /path/to/file

Bạn sẽ thấy một cái gì đó như sau ...

Thay đổi được cam kết: (sử dụng "git reset HEAD ..." để unstage)

sửa đổi: / path / to / file

Các thay đổi không được tổ chức cho cam kết: (sử dụng "git add ..." để cập nhật   những gì sẽ được cam kết) (sử dụng "git checkout - ..." để hủy   thay đổi trong thư mục làm việc)

sửa đổi: / path / to / file

  • "Thay đổi được cam kết" là phiên bản trước của tệp trước cam kết. Điều này sẽ giống như một xóa nếu tập tin không bao giờ tồn tại. Nếu bạn cam kết thay đổi này, sẽ có bản sửa đổi sẽ chuyển đổi thay đổi thành tệp trong nhánh của bạn.
  • "Thay đổi không được dàn dựng cho cam kết" là thay đổi bạn đã cam kết và trạng thái hiện tại của tệp

Tại thời điểm này, bạn có thể làm bất cứ điều gì bạn thích với tập tin, chẳng hạn như đặt lại phiên bản khác.

Khi bạn đã sẵn sàng cam kết:

git commit --amend -a

hoặc (nếu bạn có một số thay đổi khác đang diễn ra mà bạn không muốn cam kết, tuy nhiên)

git commit add /path/to/file
git commit --amend

28
2017-12-07 07:13



Câu trả lời của juzzlin là tuyệt vời, nhưng quá nhiều để unstage toàn bộ cam kết khi bạn chỉ muốn unstage một. Unstaging toàn bộ cam kết có thể gây ra vấn đề nếu bạn có hiện tại unstaged thay đổi trên các tập tin trong cam kết mà bạn không muốn mất. - ThatsAMorais


Nếu bạn muốn giữ lại cam kết của mình (có thể bạn đã dành thời gian viết một thông báo cam kết chi tiết và không muốn mất nó), và bạn chỉ muốn xóa tệp khỏi cam kết, nhưng không phải từ kho lưu trữ hoàn toàn:

git checkout origin/<remote-branch> <filename>
git commit --amend

9
2018-06-17 20:07





git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "removed unwanted file from git"

sẽ để lại cho bạn tệp cục bộ. Nếu bạn không muốn tệp cục bộ, bạn có thể bỏ qua tùy chọn --cách.

Nếu tất cả công việc là trên nhánh địa phương của bạn, bạn cần phải giữ tệp trong một lần commit sau, và giống như có một lịch sử rõ ràng, tôi nghĩ cách đơn giản hơn để thực hiện điều này có thể là:

git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit --squash <commit_id>
git add <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "brand new file!"
git rebase --interactive <commit_id>^

và sau đó bạn có thể hoàn thành việc rebase một cách dễ dàng mà không cần phải nhớ các lệnh phức tạp hơn hoặc cam kết tin nhắn hoặc nhập càng nhiều.


8
2018-02-23 06:22



Điều này làm việc cho tôi. Tôi giả sử nếu bạn muốn thêm các tập tin trở lại vào hỗn hợp, chỉ cần sử dụng git add -A hoặc git add. và họ đã trở lại. - Alexander Mills


Sử dụng git GUI có thể đơn giản hóa việc xóa một tệp khỏi cam kết trước đó.

Giả sử rằng đây không phải là một nhánh chia sẻ và bạn không phiền viết lại lịch sử, sau đó chạy:

git gui citool --amend

Bạn có thể bỏ chọn tệp đã bị nhầm lẫn và sau đó nhấp vào "Cam kết".

enter image description here

Tệp được xóa khỏi cam kết, nhưng sẽ giữ trên đĩa. Vì vậy, nếu bạn bỏ kiểm tra tệp sau khi thêm nhầm, tệp sẽ hiển thị trong danh sách tệp không được theo dõi của bạn (và nếu bạn bỏ chọn tệp sau khi sửa đổi nhầm nó sẽ hiển thị trong các thay đổi của bạn không được dàn dựng cho danh sách cam kết).


7
2018-05-18 19:50



Trên Ubuntu, bạn có thể cài đặt git gui với sudo apt-get install git-gui - JDiMatteo
Cảm ơn bạn! Tôi đã bị mắc kẹt với một vấn đề (lỗi?), Nơi một thư mục có chứa một repo .git đã được thêm vào, và tất cả các lệnh loại bỏ thường xuyên không hoạt động. Tuy nhiên điều này đã giúp. Đó là một vài cam kết trở lại, lần đầu tiên tôi sử dụng git rebase -i HEAD~4 và sau đó chạy lệnh của bạn để mở trình chỉnh sửa. Một lưu ý khác: "Unstaging" có thể được tìm thấy trong menu "Commit". - Johny Skovdal