Добавить все файлы в коммит, кроме одного?

571

У меня есть набор файлов в наборе изменений, но я хочу специально игнорировать один измененный файл. Выглядит так после git status:

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

Есть ли способ, которым я могу сделать, git addно просто игнорировать один текстовый файл, который я не хочу трогать? Что-то вроде:

git add -u -except main/dontcheckmein.txt
user291701
источник

Ответы:

851
git add -u
git reset -- main/dontcheckmein.txt
Бен Джексон
источник
28
как исключить всю папку? - основной или основной / или основной / *?
Алан Коромано
8
@MariusKavansky Вы можете использовать все эти формы. Если вы используете, main/*необходимо добавить --перед ним, чтобы git знал, что это путь. Два других варианта работают без учета двух тире. (Проверено в командной строке на Windows 7 с msysGit)
dennisschagt
2
Если у вас есть какие-то папки, которые вы хотите исключить, которые содержат огромное количество файлов или других папок: временно добавьте их в свой gitignore. git resetвпоследствии выполнение этих папок все равно будет работать, но для добавления больших папок потребуется много времени.
Майкл Троу,
2
Так что, нет одной строки?
BroVic
5
@ Бен Джексон, было бы неплохо прокомментировать каждую строку, не так ли?
ed1nh0
140

1) Чтобы начать игнорировать изменения в одном уже версионном файле

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

и отменить это git update-index --no-assume-unchanged "main/dontcheckmein.txt"

github docs игнорировать файлы

2) Полностью игнорировать определенный отдельный файл, предотвращая его создание в хранилище.

Во-первых, посмотрите на этот стековый пост: Git global ignore не работает

В .gitignore, добавьте относительный путь к файлу без начала ./.

Таким образом, если ваш файл находится в MyProject/MyFolder/myfile.txt(где .gitтакже находится в MyProjectпапке), добавьте MyFolder/myfile.txtк вашему в .gitignoreфайл.

Вы можете подтвердить, какие правила связаны с игнорированием через git check-ignore "MyFolder/myfile.txt"

О глобальном игнорировании

Эта ссылка говорит о ~/.gitignore_global, но файл относится к вашему проекту. Итак, если вы поставите исключающий шаблон MyFolder/myfile.txtв ~/.gitignore_global, он будет работать , но не имеет смысла ...

С другой стороны, если вы настроите свой проект, git config core.excludesfile .gitignoreгде .gitignoreнаходится MyProject, локальный файл будет переопределен ~/.gitignore_global, что может иметь очень полезные правила ...

Таким образом, на данный момент, я думаю , что лучше , чтобы сделать некоторый сценарий микшировать .gitignoreс ~/.gitignore_globalв .gitignore.

Одно последнее предупреждение
Если файл, который вы хотите игнорировать, уже находится в хранилище, этот метод не будет работать, если вы не сделаете этого:, git rm "MyFolder/myfile.txt"но сначала сделайте резервную копию, так как он также будет удален локально! Вы можете скопировать его позже ...

Водолей Сила
источник
5
Вы можете использовать git rm --cached MyFolder/myyfile.txtдля удаления файла из хранилища, но сохранить его локально. Пояснение на help.github.com
dennisschagt
87

Для файла

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

Для папки

git add -u
git reset -- main/*
Ритурай Ратан
источник
9
зачем нужна -u? почему нет git add . && git reset -- main/*?
2
Опция -u обновляет индекс только там, где он уже имеет запись, соответствующую <pathspec>. Это удаляет, а также изменяет записи индекса в соответствии с рабочим деревом, но не добавляет новых файлов. Если <pathspec> не указано, когда используется опция -u, все отслеживаемые файлы во всем рабочем дереве обновляются (старые версии Git использовались для ограничения обновления текущим каталогом и его подкаталогами).
Фархад Мамедли
6
Может кто-нибудь объяснить, почему -u необходим на языке, понятном не-git профи?
Патрик
2
-u используется для ссылки на вашу текущую ветку, на которую вы нажимаете. Вам больше не нужно будет печатать git push origin masterваш следующий push, просто git pushgit будет знать, что это в мастер ветке. Надеюсь, поможет.
Пепенг Хапон
69

Теперь gitподдерживает exclude certain paths and filesмагию pathspec :(exclude)и ее краткую форму :!. Таким образом, вы можете легко добиться этого как следующая команда.

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

На самом деле вы можете указать больше:

git add --all -- :!path/to/file1 :!path/to/file2 :!path/to/folder1/*
git add -- . :!path/to/file1 :!path/to/file2 :!path/to/folder1/*
кошачьи глаза
источник
1
Лучший ответ, спасибо! По крайней мере, для моего случая: мне нужно было просто исключить тип файла.
Андре Поликанин
15
Это отлично! Обратите внимание, что в Linux вам нужно заключать :!...предложения в кавычки, чтобы оболочка не жаловалась. Так, например: git add --all -- ':!path/to/file1' ':!path/to/file2' ':!path/to/folder1/*'.
Martin_W
Есть что-то подобное :!/path/to/(file1|file2)?
seeker_of_bacon
Это сталкивается с чем-то в zsh, у меня не работает на macOS и последней версии git.
Мерлин
1
Может кто-то указать, где это официально задокументировано?
samurai_jane
20

Хотя Бен Джексон прав, я подумал, что добавлю, как я использую это решение. Ниже приведен очень простой скрипт, который я использую (который я называю gitadd), чтобы добавить все изменения, кроме нескольких, которые я держу в списке в файле с именем .gittrackignore(очень похоже на то, как работает .gitignore).

#!/bin/bash
set -e

git add -A
git reset `cat .gittrackignore`

И вот как .gittrackignoreвыглядит мой нынешний .

project.properties

Я работаю над проектом Android, который я компилирую из командной строки при развертывании. Этот проект зависит от SherlockActionBar, поэтому на него нужно ссылаться в project.properties, но это мешает компиляции, так что теперь я просто набираю gitaddи добавляю все изменения в git без необходимости каждый раз удалять add.properties.

Энтони Наддео
источник
Я не знал, что --было до твоего комментария. Согласно man-страницам, это необязательно и не меняет результат команды (по крайней мере, в этом случае). Этот вопрос, кажется, подтверждает это, stackoverflow.com/questions/17800994/… . Поправьте меня, если я ошибаюсь, но кажется, что это означает «трактовать что-либо после --как аргументы, а не опции / переключатели»
Энтони Наддео
Nice использование --в git checkoutЯ вижу в этом вопросе. Я не знал, что такое двойная черта, до нашего обмена тоже. Интересно, может ли git checkoutдвусмысленность между ветками и файлами повлиять, в той или иной форме, git resetтакже.
Джулио Пьянкастелли
10

Чтобы сохранить изменения в файле, но не фиксировать, я сделал это

git add .

git reset -- main/dontcheckmein.txt

git commit -m "commit message"

чтобы убедиться, что файл исключен, сделайте

git status

gsumk
источник
4

Используйте git add -Aдля добавления всех измененных и вновь добавленных файлов одновременно.

пример

git add -A
git reset -- main/dontcheckmein.txt
Дханука Нуван
источник
4
git add .
git reset main/dontcheckmein.txt
Даниил Даниелецкий
источник
2

Попробуй это:

git checkout -- main/dontcheckmein.txt
Абдулла Аман
источник
1
это отменит все изменения main / dontcheckmein.txt.
gsumk
stackoverflow.com/questions/41101998/… Это отменит изменения
Dhanapal
1

Для конкретного случая, о котором идет речь, самым простым способом было бы добавить все файлы с расширением .c и пропустить все остальное:

git add *.c

Из git-scm (или / и man git add):

git add <pathspec>…

Файлы для добавления контента. Fileglobs (например, * .c) могут быть предоставлены для добавления всех соответствующих файлов. <...>

Обратите внимание, что это означает, что вы также можете сделать что-то вроде:

git add **/main/*

добавить все файлы (которые не игнорируются), которые находятся в mainпапке. Вы можете даже сходить с ума с более сложными образцами:

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

Выше будут добавлены все файлы, которые находятся в s(any char)cпапке и Serviceгде-то в их имени файла.

Очевидно, вы не ограничены одним шаблоном на команду. То есть вы можете попросить git добавить все файлы с расширением .c и .h :

git add *.c *.h

Эта ссылка может дать вам больше идей по шаблонам.

Я нахожу это особенно полезным, когда я делаю много изменений, но все же хочу, чтобы мои коммиты оставались атомарными и отражали постепенный процесс, а не мешанину изменений, над которыми я, возможно, работаю в то время. Конечно, в какой-то момент стоимость разработки сложных шаблонов превышает стоимость добавления файлов более простыми методами или даже одного файла за раз. Тем не менее, в большинстве случаев я легко могу указать только нужные мне файлы простым шаблоном и исключить все остальное.

Кстати, вам может понадобиться процитировать ваши шаблоны глобуса, чтобы они работали, но для меня это никогда не было так.

cegas
источник
0

Я использовал git add --patchнемного и хотел что-то вроде этого, чтобы избежать необходимости постоянно попадать dв одни и те же файлы. Я набрал пару хакерских псевдонимов, чтобы выполнить работу:

[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' )"

В моем случае я просто хотел постоянно игнорировать определенные минимизированные файлы, но вы могли бы заставить его использовать переменную окружения, как $GIT_EXCLUDE_PATTERNдля более общего случая использования.

Крис
источник
0

Изменения, которые необходимо зафиксировать: (используйте «git reset HEAD ...» для удаления)

Колин Рикелс
источник
0

Вы можете попробовать это: git add * && git reset main/dontcheckmein.txt

Родриго
источник