Thêm tất cả các tệp vào một cam kết ngoại trừ một tệp duy nhất?


571

Tôi có một loạt các tệp trong một tập tin thay đổi, nhưng tôi muốn bỏ qua một tập tin sửa đổi duy nhất. Hình như sau này git status:

# modified:   main/dontcheckmein.txt
# deleted:    main/plzcheckmein.c
# deleted:    main/plzcheckmein2.c
...

Có cách nào tôi có thể làm git addnhưng chỉ cần bỏ qua một tệp văn bản mà tôi không muốn chạm vào? Cái gì đó như:

git add -u -except main/dontcheckmein.txt

Câu trả lời:


851
git add -u
git reset -- main/dontcheckmein.txt

28
Làm thế nào để tôi loại trừ toàn bộ thư mục? - chính hay chính / hoặc chính / *?
Alan Coromano

8
@MariusKavansky Bạn có thể sử dụng tất cả các hình thức này. Nếu bạn sử dụng main/*thì cần phải thêm --vào trước nó để cho git biết rằng đó là một đường dẫn. Hai biến thể khác hoạt động mà không bao gồm hai dấu gạch ngang. (Đã thử nghiệm trong dấu nhắc lệnh trên Windows 7 với msysGit)
dennisschagt

2
Nếu bạn có một số thư mục bạn muốn loại trừ có chứa một lượng lớn tệp hoặc các thư mục khác: tạm thời thêm chúng vào gitignore của bạn. thực hiện một git resetcho các thư mục đó sau đó vẫn sẽ hoạt động, nhưng sẽ mất nhiều thời gian để thêm các thư mục lớn.
Michael Trouw

2
Vì vậy, không có một lót?
BroVic

5
@Ben Jackson sẽ rất tuyệt khi bình luận từng dòng, bạn có nghĩ vậy không?
ed1nh0

140

1) Để bắt đầu bỏ qua các thay đổi đối với một tệp đã được phiên bản

git update-index --assume-unchanged "main/dontcheckmein.txt"

và hoàn tác điều đó git update-index --no-assume-unchanged "main/dontcheckmein.txt"

tài liệu github để bỏ qua các tập tin

2) Để hoàn toàn bỏ qua một tập tin cụ thể ngăn chặn nó được tạo ra tại kho lưu trữ

Đầu tiên, hãy xem bài đăng stackoverflow này: Git global bỏ qua không hoạt động

Trong .gitignore , thêm đường dẫn tương đối vào tệp mà không dẫn ./.

Vì vậy, nếu tập tin của bạn đang ở MyProject/MyFolder/myfile.txt, (nơi .gitcũng nằm trongMyProject thư mục), hãy thêm MyFolder/myfile.txtvào .gitignoretệp của bạn .

Bạn có thể xác nhận những quy tắc nào được liên kết với bỏ qua thông qua git check-ignore "MyFolder/myfile.txt"

Về toàn cầu bỏ qua

Liên kết đó nói về ~/.gitignore_global, nhưng tập tin có liên quan đến dự án của bạn. Vì vậy, nếu bạn đặt mẫu loại trừ MyFolder/myfile.txtvào ~/.gitignore_global, nó sẽ hoạt động nhưng sẽ không có ý nghĩa nhiều ...

Mặt khác, nếu bạn thiết lập dự án của mình với git config core.excludesfile .gitignorevị trí .gitignoređang ở đâu MyProject, tệp cục bộ sẽ ghi đè lên ~/.gitignore_global, có thể có các quy tắc rất hữu ích ...

Vì vậy, bây giờ, tôi nghĩ rằng nó là tốt nhất để thực hiện một số kịch bản để trộn của bạn .gitignorevới ~/.gitignore_globaltại .gitignore.

Một cảnh báo cuối cùng
Nếu tệp bạn muốn bỏ qua đã có trong kho lưu trữ, phương pháp này sẽ không hoạt động trừ khi bạn thực hiện việc này: git rm "MyFolder/myfile.txt"nhưng hãy sao lưu trước, vì nó cũng sẽ bị xóa cục bộ! Bạn có thể sao chép lại sau ...


5
Bạn có thể sử dụng git rm --cached MyFolder/myyfile.txtđể xóa tệp khỏi kho lưu trữ nhưng giữ nó cục bộ. Giải thích về help.github.com
dennisschagt

87

Đối với một tập tin

git add -u
git reset -- main/dontcheckmein.txt

Cho một thư mục

git add -u
git reset -- main/*

9
Tại sao -u cần thiết? tại sao không git add . && git reset -- main/*?

2
Tùy chọn -u cập nhật chỉ mục khi nó đã có mục nhập khớp với <pathspec>. Điều này loại bỏ cũng như sửa đổi các mục chỉ mục để phù hợp với cây làm việc, nhưng không thêm tệp mới. Nếu không có <pathspec> được đưa ra khi tùy chọn -u được sử dụng, tất cả các tệp được theo dõi trong toàn bộ cây làm việc sẽ được cập nhật (các phiên bản cũ của Git được sử dụng để giới hạn cập nhật vào thư mục hiện tại và các thư mục con của nó).
Farhad Mammadli

6
Bất cứ ai có thể giải thích tại sao -u là cần thiết trong ngôn ngữ mà các chuyên gia không phải là git sẽ hiểu?
Patrick

2
-u được sử dụng để tham chiếu chi nhánh hiện tại của bạn. Bạn sẽ không còn cần phải gõ git push origin mastertrong lần đẩy tiếp theo của mình, chỉ cần git pushvà git sẽ biết đó là trong nhánh chính. Hy vọng nó giúp.
Pepeng Hapon

69

Bây giờ githỗ trợ exclude certain paths and filesbằng ma thuật pathspec :(exclude)và hình thức ngắn của nó :!. Vì vậy, bạn có thể dễ dàng đạt được nó như là lệnh sau.

git add --all -- :!main/dontcheckmein.txt
git add -- . :!main/dontcheckmein.txt

Trên thực tế bạn có thể chỉ định thêm:

git add --all -- :!path/to/file1 :!path/to/file2 :!path/to/folder1/*
git add -- . :!path/to/file1 :!path/to/file2 :!path/to/folder1/*

1
Câu trả lời tốt nhất, cảm ơn! Ít nhất, đối với trường hợp của tôi: tôi chỉ cần loại trừ một loại tệp.
Andre Polykanine

15
Thật tuyệt vời! Lưu ý rằng trên Linux, bạn cần trích dẫn các :!...mệnh đề để giữ cho vỏ không bị phàn nàn. Vì vậy, ví dụ : git add --all -- ':!path/to/file1' ':!path/to/file2' ':!path/to/folder1/*'.
Martin_W

Có cái gì như thế :!/path/to/(file1|file2)?
seeker_of_bacon

Điều này va chạm với một cái gì đó trong zsh, không hoạt động với tôi trên macOS và git mới nhất.
Merlin

1
Ai đó có thể chỉ ra nơi này là tài liệu chính thức?
samurai_jane

20

Trong khi Ben Jackson đúng, tôi nghĩ tôi cũng sẽ thêm cách tôi đã sử dụng giải pháp đó. Dưới đây là một tập lệnh rất đơn giản mà tôi sử dụng (mà tôi gọi là gitadd) để thêm tất cả các thay đổi ngoại trừ một số lựa chọn mà tôi giữ được liệt kê trong một tệp có tên .gittrackignore(rất giống với cách .gitignore hoạt động).

#!/bin/bash
set -e

git add -A
git reset `cat .gittrackignore`

Và đây là những gì hiện tại của tôi .gittrackignoretrông như thế nào.

project.properties

Tôi đang làm việc trên một dự án Android mà tôi biên dịch từ dòng lệnh khi triển khai. Dự án này phụ thuộc vào SherlockActionBar, do đó, nó cần được tham chiếu trong project.properations, nhưng điều đó gây rối với quá trình biên dịch, vì vậy bây giờ tôi chỉ cần gõ gitaddvà thêm tất cả các thay đổi vào git mà không phải thêm dự án.


Tôi không biết những gì --đã cho đến khi bình luận của bạn. Theo các trang man, tùy chọn của nó và không thay đổi kết quả của lệnh (ít nhất là trong trường hợp này). Câu hỏi này dường như hỗ trợ điều đó, stackoverflow.com/questions/17800994/ trên . Sửa lỗi cho tôi nếu tôi sai, nhưng có vẻ như nó có nghĩa là "coi bất cứ điều gì sau khi --là đối số, không phải là lựa chọn / công tắc"
Anthony Naddeo

Sử dụng tốt đẹp --trong git checkouttôi thấy trong câu hỏi đó. Tôi cũng không biết dấu gạch ngang kép là gì cho đến khi trao đổi này với chúng tôi. Tôi tự hỏi nếu sự git checkoutmơ hồ giữa các nhánh và tập tin có thể ảnh hưởng, dưới hình thức này hoặc một hình thức khác, git resetcũng có.
Giulio Piancastelli

10

Để giữ thay đổi trong tập tin nhưng không cam kết tôi đã làm điều này

git add .

git reset -- main/dontcheckmein.txt

git commit -m "commit message"

để xác minh tập tin bị loại

git status


4

Sử dụng git add -Ađể thêm tất cả các tệp sửa đổi và mới được thêm vào cùng một lúc.

Thí dụ

git add -A
git reset -- main/dontcheckmein.txt



1

Đối với trường hợp cụ thể trong câu hỏi, cách dễ nhất là thêm tất cả các tệp có đuôi .c và bỏ qua mọi thứ khác:

git add *.c

Từ git-scm (hoặc / và man git add):

git add <pathspec> '

Tập tin để thêm nội dung từ. Fileglobs (ví dụ * .c) có thể được cung cấp để thêm tất cả các tệp phù hợp. <...>

Lưu ý rằng điều này có nghĩa là bạn cũng có thể làm một cái gì đó như:

git add **/main/*

để thêm tất cả các tệp (không được bỏ qua) trong mainthư mục. Bạn thậm chí có thể đi hoang dã với các mẫu phức tạp hơn:

git add **/s?c/*Service*

Ở trên sẽ thêm tất cả các tập tin trong s(any char)cthư mục và cóService một nơi nào đó trong tên tệp của họ.

Rõ ràng, bạn không bị giới hạn một mẫu trên mỗi lệnh. Đó là, bạn có thể yêu cầu git thêm tất cả các tệp có phần mở rộng là .c.h :

git add *.c *.h

Liên kết này có thể cung cấp cho bạn một số ý tưởng mô hình toàn cầu hơn.

Tôi thấy nó đặc biệt hữu ích khi tôi thực hiện nhiều thay đổi, nhưng vẫn muốn các cam kết của mình duy trì nguyên tử và phản ánh quá trình dần dần thay vì một loạt các thay đổi mà tôi có thể đang làm việc vào thời điểm đó. Tất nhiên, tại một số điểm, chi phí phát sinh với các mẫu phức tạp vượt xa chi phí thêm tệp bằng các phương pháp đơn giản hơn hoặc thậm chí một tệp mỗi lần. Tuy nhiên, hầu hết thời gian tôi có thể dễ dàng xác định chính xác các tệp tôi cần với một mẫu đơn giản và loại trừ mọi thứ khác.

Nhân tiện, bạn có thể cần trích dẫn các mẫu toàn cầu của mình để chúng hoạt động, nhưng điều này không bao giờ đúng với tôi.


0

Tôi sử dụng git add --patchkhá nhiều và muốn một cái gì đó như thế này để tránh phải đánh dtất cả các tệp thông qua cùng một lúc. Tôi đã đánh cắp một vài bí danh git để hoàn thành công việc:

[alias]
    HELPER-CHANGED-FILTERED = "!f() { git status --porcelain | cut -c4- | ( [[ \"$1\" ]] && egrep -v \"$1\" || cat ); }; f"
    ap                      = "!git add --patch -- $(git HELPER-CHANGED-FILTERED 'min.(js|css)$' || echo 'THIS_FILE_PROBABLY_DOESNT_EXIST' )"

Trong trường hợp của tôi, tôi chỉ muốn bỏ qua các tệp được rút gọn nhất định mọi lúc, nhưng bạn có thể làm cho nó sử dụng một biến môi trường như $GIT_EXCLUDE_PATTERNđối với trường hợp sử dụng chung hơn.


0

Các thay đổi được cam kết: (sử dụng "git reset HEAD ..." để hủy bỏ)


0

Bạn có thể thử điều này: git add * && git reset main/dontcheckmein.txt

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.