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

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

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

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

git add -u -except main/dontcheckmein.txt

20 ответов

Решение
git add -u
git reset -- main/dontcheckmein.txt

Сейчас git опоры exclude certain paths and files магией пути :(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) Чтобы начать игнорировать изменения в одном уже версионном файле

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

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

проверьте здесь

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

Первый взгляд на этот Git Global игнорировать не работает

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

так что если ваш файл в MyProject/MyFolder/myfile.txt (где .git также в MyProject), в .gitignore ты положил только это MyFolder/myfile.txt

Вы можете подтвердить, какое правило относится к игнорированию с помощью 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", но сначала сделайте резервную копию, так как она также будет удалена локально! Вы можете скопировать его позже...

Для файла

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

Для папки

git add -u
git reset -- main/*

Git предоставляет :(exclude)префикс pathspecs для исключаемых путей.

Его короткая магическая подпись — .
Документация: https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-exclude

      git add . :^main/dontcheckmein.txt

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


Если вы похожи на меня — всегда проверяйте, что будет зафиксировано с помощью -pфлаг в git addкоманда — :^магическая подпись тоже работает как шарм:

      git add -p . :^main/dontcheckmein.txt

Хотя Бен Джексон прав, я подумал, что добавлю, как я использовал это решение. Ниже приведен очень простой скрипт, который я использую (который я называю 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.

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

git add .

git reset -- main/dontcheckmein.txt

git commit -m "commit message"

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

git status

git add .
git reset main/dontcheckmein.txt

Мы можем добавить все файлы и исключить файл, который необходимо удалить с помощью git reset.

      git add .
git reset -- <file_name_to_exclude>

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

пример

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

добавить все файлы

git добавить .

получить путь к файлу для вставки ниже

статус git

удалить из коммита

git reset -- файл/к/путь/файл-к-игнорированию.txt

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

git add *.c

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

git add

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

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

git add **/main/*

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

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

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

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

git add *.c *.h

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

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

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

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

git checkout - main/dontcheckmein.txt

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

После добавления всех файлов в промежуточную область через

      git add -u

печатание git statusпредложит вам

      git restore --staged main/dontcheckmein.txt

вы можете использовать рекомендации git

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

      git add .
git restore --staged <file_not_push>

Если вы хотите игнорировать определенный файл каждый раз, есть три эффективных решения, не связанных с файлами .

  1. Добавьте файл, который вы хотите игнорировать, в .git/info/exclude. Он работает так же, как ваш .gitignore, за исключением того, что конфигурация специфична для вашей машины .

  2. Сбросьте файл, который вы хотите использовать, с помощью git hook перед фиксацией . Например:

            $ echo 'git reset -- src/main/resources/log4j.properties' >> .git/hooks/pre-commit
    $ chmod +x .git/hooks/pre-commit
    

    Хук pre-commit запускается непосредственно перед фиксацией. Таким образом, ваши файлы могут быть автоматически сброшены перед каждым коммитом.

            $ git status
    On branch CHANGE-137-notifications-support ...
    
    Changes not staged for commit:
     modified:   Dockerfile
     modified:   src/main/resources/log4j.properties
    
    $ git add .
    
    $ git status
    On branch CHANGE-137-notifications-support ...
    
    Changes to be committed:
     modified:   Dockerfile
     modified:   src/main/resources/log4j.properties
    
    
    $ git commit -m "Trivial change"
    
    Unstaged changes after reset:
    M    src/main/resources/log4j.properties
    
    [CHANGE-137-notifications-support 97cfb3f] Trivial change
    1 file changed, 3 insertions(+)
    
  3. Третий способ — обновить индекс для конкретного файла.

            $ git update-index --assume-unchanged src/main/resources/log4j.properties
    

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

Согласно книге Pro Git .
Скотт Чакон, Бен Штрауб.
Есть 2 подхода к достижению:

git сброс

      $ git reset HEAD main/dontcheckmein.txt

В Git версии 2.23.0 появилась новая команда: git restoration . По сути, это альтернатива git reset, о котором мы только что рассказали. Начиная с версии Git 2.23.0, Git будет использовать git Restoration вместо git Reset для многих операций отмены.

git восстановление

      $ git restore --staged main/dontcheckmein.txt

:warning: Важно понимать, что git restre <file> — опасная команда. Любые локальные изменения, внесенные вами в этот файл, исчезли — Git просто заменил этот файл последней подготовленной или зафиксированной версией. Никогда не используйте эту команду, если вы не уверены, что вам не нужны эти несохраненные локальные изменения.

:предупреждение: Это правда, что команда git reset может быть опасной, особенно если вы указали флаг --hard . Однако в описанном выше сценарии файл в вашем рабочем каталоге не затрагивается, поэтому это относительно безопасно.

Я использую 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 для более общего случая использования.

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

Другие вопросы по тегам