Додати всі файли до комісії, крім одного файлу?


571

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

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

Чи є спосіб зробити це, git addале просто проігнорувати один текстовий файл, якого я не хочу торкатися? Щось на зразок:

git add -u -except main/dontcheckmein.txt

Відповіді:


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
@Ben Jackson було б добре прокоментувати кожен рядок, ви не думаєте?
ed1nh0

140

1) Початок ігнорувати зміни в одному вже перетвореному файлі

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

і скасувати це git update-index --no-assume-unchanged "main/dontcheckmein.txt"

github docs для ігнорування файлів

2) Повністю ігнорувати конкретний єдиний файл, що не дозволяє йому створюватись у сховищі

Спочатку подивіться на цей пост stackoverflow: глобальна ігнорування Git не працює

В .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
чому -у необхідний? чому ні git add . && git reset -- main/*?

2
Опція -u оновлює індекс саме там, де вже є запис, що відповідає <pathspec>. Це видаляє, а також змінює записи індексу, щоб відповідати робочому дереву, але не додає нових файлів. Якщо при використанні параметра -u не вказано <pathspec>, усі відстежувані файли у всьому робочому дереві оновлюються (старі версії Git використовуються для обмеження оновлення до поточного каталогу та його підкаталогів).
Фархад Мамедлі

6
Чи може хто-небудь пояснити, чому -u необхідний у мові, яку зрозуміють non-git профі?
Патрік

2
-u використовується для посилання на вашу поточну гілку, на яку ви натискаєте. Вам більше не потрібно буде вводити git push origin masterнаступний набір, просто git pushі git дізнається, що це в головній галузі. Сподіваюся, це допомагає.
Pepeng Hapon,

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, не потребуючи кожного разу додавати project.properties.


Я не знав, що --було до вашого коментаря. Згідно з довідковими сторінками, його вибір необов'язковий і не змінює результат команди (принаймні в цьому випадку). Це питання, схоже, підтримує це, 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


4

Використовуйте git add -Aдля додавання всіх змінених та нещодавно доданих файлів одночасно.

Приклад

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



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

Це посилання може дати вам ще кілька ідей глобального шаблону.

Я вважаю це особливо корисним, коли я вношу багато змін, але все ж хочу, щоб мої зобов’язання залишалися атомними та відображали поступовий процес, а не міграцію змін, над якими я можу працювати в той час. Звичайно, в якийсь момент вартість розробки складних шаблонів перевищує вартість додавання файлів більш простими методами або навіть одним файлом за один раз. Однак більшу частину часу мені легко вдається чітко визначити лише потрібні мені файли за допомогою простого шаблону та виключити все інше.

До речі, вам може знадобитися цитувати свої глобальні зразки, щоб вони працювали, але мені це ніколи не було.


0

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

[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для більш загального випадку використання.



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.