Git игнорирует папку как исправить

I have a cloned repo. There's a directory, call it a/b/c that used to be its own repo, i.e. there was a/b/c/.git/ etc. Now I want the files managed in the main repo. I don't care about the history...

I have a cloned repo. There’s a directory, call it a/b/c that used to be its own repo, i.e. there was a/b/c/.git/ etc.

Now I want the files managed in the main repo. I don’t care about the history in a/b/c, so I deleted the .git dir in a/b/c

But the problem is that git status is ignoring a/b/c completely. I can’t git add it. It’s as though I’d put the path into .gitignore (I haven’t).

Obviously before, it made sense for git to ignore a subdir with a .git dir in it, but now how does it know the difference?

Is there somewhere else that ignore files are listed other than .gitignore and .git/info/excludes? There’s nothing in the .git/config file?

I’ve been asked what git status says. Not much:

/path/to/root/dir $ git status
# On branch fred
nothing to commit (working directory clean)

And what git add says. Even less (nothing)

/path/to/root/dir $ git add a/b/c

asked May 25, 2012 at 17:41

artfulrobot's user avatar

artfulrobotartfulrobot

20.1k11 gold badges51 silver badges80 bronze badges

10

I have no idea what the problem was or how it arose (v. annoying), but here is how I fixed it, in case anyone else gets stuck:

git rm --cached a/b/c
git commit -m "removed phantom a/b/c dir"
git add a/b/c
git commit -m "finally able to add a/b/c"

Interestingly git log a/b/c only lists the «finally able…» commit. git show HEAD^ (the «removed phantom…» commit says

-Subproject commit c311ccdc91c8be66019aa138d1c4af49a6b7a81c

So it looks like it was treating it specially some how. I’m going to have to read up more on subprojects and/or submodules.

answered May 25, 2012 at 18:56

artfulrobot's user avatar

artfulrobotartfulrobot

20.1k11 gold badges51 silver badges80 bronze badges

5

Do you have a global gitignore file ? (Check with git config core.excludesfile)

answered May 25, 2012 at 17:42

ksol's user avatar

ksolksol

11.7k5 gold badges36 silver badges64 bronze badges

1

Appears that an empty directory basically does not exist for Git. And if all files in a directory match .gitignore patterns, then git treats the directory as empty.

I had this happen on a directory with a foo.tgz file, and at the root of the repo the .gitignore file had the pattern *.tgz. Very frustrating that the git check-ignore command doesn’t report something like «hey noob the directory looks empty to me».

Next time try this:

git check-ignore strangely-ignored-directory/*

That output just may solve the mystery.

answered Jul 24, 2019 at 20:17

chrisinmtown's user avatar

chrisinmtownchrisinmtown

3,1543 gold badges32 silver badges42 bronze badges

1

Use git add -f to force git to add files it is currently ignoring.

answered Mar 6, 2018 at 21:35

gsganden's user avatar

2

Summary: Are your .gitignore files (Including any in the directory itself) ignoring everything the directory contains. If so Git will treat it as empty and not list it)

I had a similar problem. I discovered that the directory that was being ignored contained a .gitignore file (Though not a .git directory). Upon removing it git was suddenly interested in it again and listed it as an untracked file/directory in git status.

When I restored the original contents of the .gitignore by pasting them back from earlier in the terminal git again doesn’t see or list the directory as untracked.

Through trial and error I discovered that I could delete everything from the .gitignore except the following entries:

.factorypath
.springBeans

If both of those lines are in the .gitignore file then the containing directory (Which is not the root of the git repository) is not seen by git.

This raises more questions than it answers for me.

Here is a listing of the directory, but I cannot see a pattern.

total 72
drwxr-xr-x@ 10 stephen  staff    320 30 Aug 19:04 .
drwxr-xr-x  17 stephen  staff    544 30 Aug 18:59 ..
drwxr-xr-x   2 stephen  staff     64 25 Jun 15:00 .apt_generated
-rw-r--r--   1 stephen  staff   1341 25 Jun 15:00 .classpath
-rw-r--r--   1 stephen  staff  18665 28 Jun 10:44 .factorypath
-rw-r--r--@  1 stephen  staff     25 30 Aug 19:12 .gitignore
-rw-r--r--   1 stephen  staff   1094 28 Jun 10:44 .project
drwxr-xr-x   7 stephen  staff    224 25 Jun 15:00 .settings
-rw-r--r--   1 stephen  staff    479 28 Jun 15:43 .springBeans
drwxr-xr-x   6 stephen  staff    192  2 Jul 12:41 target

answered Aug 30, 2018 at 18:17

spl's user avatar

splspl

5004 silver badges13 bronze badges

1

This problem occurred for me just now because I had used create-react-app to initialise a client app inside a top-level folder todo controlled by git:

cd todo
npx create-react-app client --template typescript

Under the hood this created a folder client that had a .git directory and also a .gitignore file. It was like a git subproject.

When I added the project via git add -i to source control, a weird empty directory pointer was created but with no contents.

I used the command

git rm --cached client

…which removed the weird empty directory/pointer that git was storing. But when I tried to add the folder I got this message:

~/depot/todo $ git add client
warning: adding embedded git repository: client
hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
hint: the embedded repository and will not know how to obtain it.
hint: If you meant to add a submodule, use:
hint: 
hint:   git submodule add <url> client
hint: 
hint: If you added this path by mistake, you can remove it from the
hint: index with:
hint: 
hint:   git rm --cached client
hint: 
hint: See "git help submodule" for more information.

To fix this I removed the git artifacts and from then I could commit as normal.

rm -Rf client/.git
rm -f client/.gitignore
git add client
git commit -m "Add missing client content"

answered Mar 27, 2021 at 6:02

Sez's user avatar

SezSez

1,25511 silver badges26 bronze badges

I have a cloned repo. There’s a directory, call it a/b/c that used to be its own repo, i.e. there was a/b/c/.git/ etc.

Now I want the files managed in the main repo. I don’t care about the history in a/b/c, so I deleted the .git dir in a/b/c

But the problem is that git status is ignoring a/b/c completely. I can’t git add it. It’s as though I’d put the path into .gitignore (I haven’t).

Obviously before, it made sense for git to ignore a subdir with a .git dir in it, but now how does it know the difference?

Is there somewhere else that ignore files are listed other than .gitignore and .git/info/excludes? There’s nothing in the .git/config file?

I’ve been asked what git status says. Not much:

/path/to/root/dir $ git status
# On branch fred
nothing to commit (working directory clean)

And what git add says. Even less (nothing)

/path/to/root/dir $ git add a/b/c

asked May 25, 2012 at 17:41

artfulrobot's user avatar

artfulrobotartfulrobot

20.1k11 gold badges51 silver badges80 bronze badges

10

I have no idea what the problem was or how it arose (v. annoying), but here is how I fixed it, in case anyone else gets stuck:

git rm --cached a/b/c
git commit -m "removed phantom a/b/c dir"
git add a/b/c
git commit -m "finally able to add a/b/c"

Interestingly git log a/b/c only lists the «finally able…» commit. git show HEAD^ (the «removed phantom…» commit says

-Subproject commit c311ccdc91c8be66019aa138d1c4af49a6b7a81c

So it looks like it was treating it specially some how. I’m going to have to read up more on subprojects and/or submodules.

answered May 25, 2012 at 18:56

artfulrobot's user avatar

artfulrobotartfulrobot

20.1k11 gold badges51 silver badges80 bronze badges

5

Do you have a global gitignore file ? (Check with git config core.excludesfile)

answered May 25, 2012 at 17:42

ksol's user avatar

ksolksol

11.7k5 gold badges36 silver badges64 bronze badges

1

Appears that an empty directory basically does not exist for Git. And if all files in a directory match .gitignore patterns, then git treats the directory as empty.

I had this happen on a directory with a foo.tgz file, and at the root of the repo the .gitignore file had the pattern *.tgz. Very frustrating that the git check-ignore command doesn’t report something like «hey noob the directory looks empty to me».

Next time try this:

git check-ignore strangely-ignored-directory/*

That output just may solve the mystery.

answered Jul 24, 2019 at 20:17

chrisinmtown's user avatar

chrisinmtownchrisinmtown

3,1543 gold badges32 silver badges42 bronze badges

1

Use git add -f to force git to add files it is currently ignoring.

answered Mar 6, 2018 at 21:35

gsganden's user avatar

2

Summary: Are your .gitignore files (Including any in the directory itself) ignoring everything the directory contains. If so Git will treat it as empty and not list it)

I had a similar problem. I discovered that the directory that was being ignored contained a .gitignore file (Though not a .git directory). Upon removing it git was suddenly interested in it again and listed it as an untracked file/directory in git status.

When I restored the original contents of the .gitignore by pasting them back from earlier in the terminal git again doesn’t see or list the directory as untracked.

Through trial and error I discovered that I could delete everything from the .gitignore except the following entries:

.factorypath
.springBeans

If both of those lines are in the .gitignore file then the containing directory (Which is not the root of the git repository) is not seen by git.

This raises more questions than it answers for me.

Here is a listing of the directory, but I cannot see a pattern.

total 72
drwxr-xr-x@ 10 stephen  staff    320 30 Aug 19:04 .
drwxr-xr-x  17 stephen  staff    544 30 Aug 18:59 ..
drwxr-xr-x   2 stephen  staff     64 25 Jun 15:00 .apt_generated
-rw-r--r--   1 stephen  staff   1341 25 Jun 15:00 .classpath
-rw-r--r--   1 stephen  staff  18665 28 Jun 10:44 .factorypath
-rw-r--r--@  1 stephen  staff     25 30 Aug 19:12 .gitignore
-rw-r--r--   1 stephen  staff   1094 28 Jun 10:44 .project
drwxr-xr-x   7 stephen  staff    224 25 Jun 15:00 .settings
-rw-r--r--   1 stephen  staff    479 28 Jun 15:43 .springBeans
drwxr-xr-x   6 stephen  staff    192  2 Jul 12:41 target

answered Aug 30, 2018 at 18:17

spl's user avatar

splspl

5004 silver badges13 bronze badges

1

This problem occurred for me just now because I had used create-react-app to initialise a client app inside a top-level folder todo controlled by git:

cd todo
npx create-react-app client --template typescript

Under the hood this created a folder client that had a .git directory and also a .gitignore file. It was like a git subproject.

When I added the project via git add -i to source control, a weird empty directory pointer was created but with no contents.

I used the command

git rm --cached client

…which removed the weird empty directory/pointer that git was storing. But when I tried to add the folder I got this message:

~/depot/todo $ git add client
warning: adding embedded git repository: client
hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
hint: the embedded repository and will not know how to obtain it.
hint: If you meant to add a submodule, use:
hint: 
hint:   git submodule add <url> client
hint: 
hint: If you added this path by mistake, you can remove it from the
hint: index with:
hint: 
hint:   git rm --cached client
hint: 
hint: See "git help submodule" for more information.

To fix this I removed the git artifacts and from then I could commit as normal.

rm -Rf client/.git
rm -f client/.gitignore
git add client
git commit -m "Add missing client content"

answered Mar 27, 2021 at 6:02

Sez's user avatar

SezSez

1,25511 silver badges26 bronze badges

Запись изменений в репозиторий

Итак, у вас имеется настоящий Git-репозиторий и рабочая копия файлов для некоторого проекта.
Вам нужно делать некоторые изменения и фиксировать «снимки» состояния (snapshots) этих изменений в вашем репозитории каждый раз, когда проект достигает состояния, которое вам хотелось бы сохранить.

Запомните, каждый файл в вашем рабочем каталоге может находиться в одном из двух состояний: под версионным контролем (отслеживаемые) и нет (неотслеживаемые).
Отслеживаемые файлы — это те файлы, которые были в последнем снимке состояния проекта; они могут быть неизменёнными, изменёнными или подготовленными к коммиту.
Если кратко, то отслеживаемые файлы — это те файлы, о которых знает Git.

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

Как только вы отредактируете файлы, Git будет рассматривать их как изменённые, так как вы изменили их с момента последнего коммита.
Вы индексируете эти изменения, затем фиксируете все проиндексированные изменения, а затем цикл повторяется.

Жизненный цикл состояний файлов

Рисунок 8. Жизненный цикл состояний файлов

Определение состояния файлов

Основной инструмент, используемый для определения, какие файлы в каком состоянии находятся — это команда git status.
Если вы выполните эту команду сразу после клонирования, вы увидите что-то вроде этого:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean

Это означает, что у вас чистый рабочий каталог, другими словами — в нем нет отслеживаемых измененных файлов.
Git также не обнаружил неотслеживаемых файлов, в противном случае они бы были перечислены здесь.
Наконец, команда сообщает вам на какой ветке вы находитесь и сообщает вам, что она не расходится с веткой на сервере.
Пока что это всегда ветка master, ветка по умолчанию; в этой главе это не важно.
В главе Ветвление в Git будут рассмотрены ветки и ссылки более детально.

Предположим, вы добавили в свой проект новый файл, простой файл README.
Если этого файла раньше не было, и вы выполните git status, вы увидите свой неотслеживаемый файл вот так:

$ echo 'My Project' > README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    README

nothing added to commit but untracked files present (use "git add" to track)

Понять, что новый файл README неотслеживаемый можно по тому, что он находится в секции «Untracked files» в выводе команды status.
Статус Untracked означает, что Git видит файл, которого не было в предыдущем снимке состояния (коммите); Git не станет добавлять его в ваши коммиты, пока вы его явно об этом не попросите.
Это предохранит вас от случайного добавления в репозиторий сгенерированных бинарных файлов или каких-либо других, которые вы и не думали добавлять.
Мы хотели добавить README, так давайте сделаем это.

Отслеживание новых файлов

Для того чтобы начать отслеживать (добавить под версионный контроль) новый файл, используется команда git add.
Чтобы начать отслеживание файла README, вы можете выполнить следующее:

Если вы снова выполните команду status, то увидите, что файл README теперь отслеживаемый и добавлен в индекс:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)

    new file:   README

Вы можете видеть, что файл проиндексирован, так как он находится в секции «Changes to be committed».
Если вы выполните коммит в этот момент, то версия файла, существовавшая на момент выполнения вами команды git add, будет добавлена в историю снимков состояния.
Как вы помните, когда вы ранее выполнили git init, затем вы выполнили git add (файлы) — это было сделано для того, чтобы добавить файлы в вашем каталоге под версионный контроль.
Команда git add принимает параметром путь к файлу или каталогу, если это каталог, команда рекурсивно добавляет все файлы из указанного каталога в индекс.

Индексация изменённых файлов

Давайте модифицируем файл, уже находящийся под версионным контролем.
Если вы измените отслеживаемый файл CONTRIBUTING.md и после этого снова выполните команду git status, то результат будет примерно следующим:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Файл CONTRIBUTING.md находится в секции «Changes not staged for commit» — это означает, что отслеживаемый файл был изменён в рабочем каталоге, но пока не проиндексирован.
Чтобы проиндексировать его, необходимо выполнить команду git add.
Это многофункциональная команда, она используется для добавления под версионный контроль новых файлов, для индексации изменений, а также для других целей, например для указания файлов с исправленным конфликтом слияния.
Вам может быть понятнее, если вы будете думать об этом как «добавить этот контент в следующий коммит», а не как «добавить этот файл в проект».
Выполним git add, чтобы проиндексировать CONTRIBUTING.md, а затем снова выполним git status:

$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

Теперь оба файла проиндексированы и войдут в следующий коммит.
В этот момент вы, предположим, вспомнили одно небольшое изменение, которое вы хотите сделать в CONTRIBUTING.md до коммита.
Вы открываете файл, вносите и сохраняете необходимые изменения и вроде бы готовы к коммиту.
Но давайте-ка ещё раз выполним git status:

$ vim CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Что за чёрт?
Теперь CONTRIBUTING.md отображается как проиндексированный и непроиндексированный одновременно.
Как такое возможно?
Такая ситуация наглядно демонстрирует, что Git индексирует файл в точности в том состоянии, в котором он находился, когда вы выполнили команду git add.
Если вы выполните коммит сейчас, то файл CONTRIBUTING.md попадёт в коммит в том состоянии, в котором он находился, когда вы последний раз выполняли команду git add , а не в том, в котором он находится в вашем рабочем каталоге в момент выполнения git commit.
Если вы изменили файл после выполнения git add, вам придётся снова выполнить git add, чтобы проиндексировать последнюю версию файла:

$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

Сокращенный вывод статуса

Вывод команды git status довольно всеобъемлющий и многословный.
Git также имеет флаг вывода сокращенного статуса, так что вы можете увидеть изменения в более компактном виде.
Если вы выполните git status -s или git status --short вы получите гораздо более упрощенный вывод:

$ git status -s
 M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt

Новые неотслеживаемые файлы помечены ?? слева от них, файлы добавленные в отслеживаемые помечены A, отредактированные файлы помечены M и так далее.
В выводе содержится два столбца — в левом указывается статус файла, а в правом модифицирован ли он после этого.
К примеру в нашем выводе, файл README модифицирован в рабочем каталоге, но не проиндексирован, а файл lib/simplegit.rb модифицирован и проиндексирован.
Файл Rakefile модифицирован, проиндексирован и ещё раз модифицирован, таким образом на данный момент у него есть те изменения, которые попадут в коммит, и те, которые не попадут.

Игнорирование файлов

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

$ cat .gitignore
*.[oa]
*~

Первая строка предписывает Git игнорировать любые файлы заканчивающиеся на «.o» или «.a» — объектные и архивные файлы, которые могут появиться во время сборки кода.
Вторая строка предписывает игнорировать все файлы заканчивающиеся на тильду (~), которая используется во многих текстовых редакторах, например Emacs, для обозначения временных файлов.
Вы можете также включить каталоги log, tmp или pid; автоматически создаваемую документацию; и т. д. и т. п.
Хорошая практика заключается в настройке файла .gitignore до того, как начать серьёзно работать, это защитит вас от случайного добавления в репозиторий файлов, которых вы там видеть не хотите.

К шаблонам в файле .gitignore применяются следующие правила:

  • Пустые строки, а также строки, начинающиеся с #, игнорируются.

  • Стандартные шаблоны являются глобальными и применяются рекурсивно для всего дерева каталогов.

  • Чтобы избежать рекурсии используйте символ слеш (/) в начале шаблона.

  • Чтобы исключить каталог добавьте слеш (/) в конец шаблона.

  • Можно инвертировать шаблон, использовав восклицательный знак (!) в качестве первого символа.

Glob-шаблоны представляют собой упрощённые регулярные выражения, используемые командными интерпретаторами.
Символ (*) соответствует 0 или более символам; последовательность [abc] — любому символу из указанных в скобках (в данном примере a, b или c); знак вопроса (?) соответствует одному символу; и квадратные скобки, в которые заключены символы, разделённые дефисом ([0-9]), соответствуют любому символу из интервала (в данном случае от 0 до 9).
Вы также можете использовать две звёздочки, чтобы указать на вложенные каталоги: a/**/z соответствует a/z, a/b/z, a/b/c/z, и так далее.

Вот ещё один пример файла .gitignore:

# Исключить все файлы с расширением .a
*.a

# Но отслеживать файл lib.a даже если он подпадает под исключение выше
!lib.a

# Исключить файл TODO в корневом каталоге, но не файл в subdir/TODO
/TODO

# Игнорировать все файлы в каталоге build/
build/

# Игнорировать файл doc/notes.txt, но не файл doc/server/arch.txt
doc/*.txt

# Игнорировать все .txt файлы в каталоге doc/
doc/**/*.txt

Подсказка

GitHub поддерживает довольно полный список примеров .gitignore файлов для множества проектов и языков https://github.com/github/gitignore это может стать отправной точкой для .gitignore в вашем проекте.

Примечание

В простейшем случае репозиторий будет иметь один файл .gitignore в корневом каталоге, правила из которого будут рекурсивно применяться ко всем подкаталогам.
Так же возможно использовать .gitignore файлы в подкаталогах.
Правила из этих файлов будут применяться только к каталогам, в которых они находятся.
Например, репозиторий исходного кода ядра Linux содержит 206 файлов .gitignore.

Детальное рассмотрение использования нескольких .gitignore файлов выходит за пределы этой книги; детали доступны в справке man gitignore.

Просмотр индексированных и неиндексированных изменений

Если результат работы команды git status недостаточно информативен для вас — вам хочется знать, что конкретно поменялось, а не только какие файлы были изменены — вы можете использовать команду git diff.
Позже мы рассмотрим команду git diff подробнее; вы, скорее всего, будете использовать эту команду для получения ответов на два вопроса: что вы изменили, но ещё не проиндексировали, и что вы проиндексировали и собираетесь включить в коммит.
Если git status отвечает на эти вопросы в самом общем виде, перечисляя имена файлов, git diff показывает вам непосредственно добавленные и удалённые строки — патч как он есть.

Допустим, вы снова изменили и проиндексировали файл README, а затем изменили файл CONTRIBUTING.md без индексирования.
Если вы выполните команду git status, вы опять увидите что-то вроде:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Чтобы увидеть, что же вы изменили, но пока не проиндексировали, наберите git diff без аргументов:

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
 Please include a nice description of your changes when you submit your PR;
 if we have to read the whole diff to figure out why you're contributing
 in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if you patch is
+longer than a dozen lines.

 If you are starting to work on a particular area, feel free to submit a PR
 that highlights your work in progress (and note in the PR title that it's

Эта команда сравнивает содержимое вашего рабочего каталога с содержимым индекса.
Результат показывает ещё не проиндексированные изменения.

Если вы хотите посмотреть, что вы проиндексировали и что войдёт в следующий коммит, вы можете выполнить git diff --staged.
Эта команда сравнивает ваши проиндексированные изменения с последним коммитом:

$ git diff --staged
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+My Project

Важно отметить, что git diff сама по себе не показывает все изменения сделанные с последнего коммита — только те, что ещё не проиндексированы.
Такое поведение может сбивать с толку, так как если вы проиндексируете все свои изменения, то git diff ничего не вернёт.

Другой пример: вы проиндексировали файл CONTRIBUTING.md и затем изменили его, вы можете использовать git diff для просмотра как проиндексированных изменений в этом файле, так и тех, что пока не проиндексированы.
Если наше окружение выглядит вот так:

$ git add CONTRIBUTING.md
$ echo '# test line' >> CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   CONTRIBUTING.md

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

Используйте git diff для просмотра непроиндексированных изменений

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 643e24f..87f08c8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -119,3 +119,4 @@ at the
 ## Starter Projects

 See our [projects list](https://github.com/libgit2/libgit2/blob/development/PROJECTS.md).
+# test line

а так же git diff --cached для просмотра проиндексированных изменений (--staged и --cached синонимы):

$ git diff --cached
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
 Please include a nice description of your changes when you submit your PR;
 if we have to read the whole diff to figure out why you're contributing
 in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if you patch is
+longer than a dozen lines.

 If you are starting to work on a particular area, feel free to submit a PR
 that highlights your work in progress (and note in the PR title that it's

Примечание

Git Diff во внешних инструментах

Мы будем продолжать использовать команду git diff различными способами на протяжении всей книги.
Существует еще один способ просматривать эти изменения, если вы предпочитаете графический просмотр или внешнюю программу просмотра различий, вместо консоли.
Выполнив команду git difftool вместо git diff, вы сможете просмотреть изменения в файле с помощью таких программ как emerge, vimdiff и других (включая коммерческие продукты).
Выполните git difftool --tool-help чтобы увидеть какие из них уже установлены в вашей системе.

Коммит изменений

Теперь, когда ваш индекс находится в таком состоянии, как вам и хотелось, вы можете зафиксировать свои изменения.
Запомните, всё, что до сих пор не проиндексировано — любые файлы, созданные или изменённые вами, и для которых вы не выполнили git add после редактирования — не войдут в этот коммит.
Они останутся изменёнными файлами на вашем диске.
В нашем случае, когда вы в последний раз выполняли git status, вы видели что всё проиндексировано, и вот, вы готовы к коммиту.
Простейший способ зафиксировать изменения — это набрать git commit:

Эта команда откроет выбранный вами текстовый редактор.

Примечание

Редактор устанавливается переменной окружения EDITOR — обычно это vim или emacs, хотя вы можете установить любой другой с помощью команды git config --global core.editor, как было показано в главе Введение).

В редакторе будет отображён следующий текст (это пример окна Vim):

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Your branch is up-to-date with 'origin/master'.
#
# Changes to be committed:
#	new file:   README
#	modified:   CONTRIBUTING.md
#
~
~
~
".git/COMMIT_EDITMSG" 9L, 283C

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

Примечание

Для ещё более подробного напоминания, что же именно вы поменяли, можете передать аргумент -v в команду git commit.
Это приведёт к тому, что в комментарий будет также помещена дельта/diff изменений, таким образом вы сможете точно увидеть все изменения которые вы совершили.

Когда вы выходите из редактора, Git создаёт для вас коммит с этим сообщением, удаляя комментарии и вывод команды diff.

Есть и другой способ — вы можете набрать свой комментарий к коммиту в командной строке вместе с командой commit указав его после параметра -m, как в следующем примере:

$ git commit -m "Story 182: fix benchmarks for speed"
[master 463dc4f] Story 182: fix benchmarks for speed
 2 files changed, 2 insertions(+)
 create mode 100644 README

Итак, вы создали свой первый коммит!
Вы можете видеть, что коммит вывел вам немного информации о себе: на какую ветку вы выполнили коммит (master), какая контрольная сумма SHA-1 у этого коммита (463dc4f), сколько файлов было изменено, а также статистику по добавленным/удалённым строкам в этом коммите.

Запомните, что коммит сохраняет снимок состояния вашего индекса.
Всё, что вы не проиндексировали, так и висит в рабочем каталоге как изменённое; вы можете сделать ещё один коммит, чтобы добавить эти изменения в репозиторий.
Каждый раз, когда вы делаете коммит, вы сохраняете снимок состояния вашего проекта, который позже вы можете восстановить или с которым можно сравнить текущее состояние.

Игнорирование индексации

Несмотря на то, что индекс может быть удивительно полезным для создания коммитов именно такими, как вам и хотелось, он временами несколько сложнее, чем вам нужно в процессе работы.
Если у вас есть желание пропустить этап индексирования, Git предоставляет простой способ.
Добавление параметра -a в команду git commit заставляет Git автоматически индексировать каждый уже отслеживаемый на момент коммита файл, позволяя вам обойтись без git add:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   CONTRIBUTING.md

no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'Add new benchmarks'
[master 83e38c7] Add new benchmarks
 1 file changed, 5 insertions(+), 0 deletions(-)

Обратите внимание, что в данном случае перед коммитом вам не нужно выполнять git add для файла CONTRIBUTING.md, потому что флаг -a включает все файлы.
Это удобно, но будьте осторожны: флаг -a может включить в коммит нежелательные изменения.

Удаление файлов

Для того чтобы удалить файл из Git, вам необходимо удалить его из отслеживаемых файлов (точнее, удалить его из вашего индекса) а затем выполнить коммит.
Это позволяет сделать команда git rm, которая также удаляет файл из вашего рабочего каталога, так что в следующий раз вы не увидите его как «неотслеживаемый».

Если вы просто удалите файл из своего рабочего каталога, он будет показан в секции «Changes not staged for commit» (измененные, но не проиндексированные) вывода команды git status:

$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    PROJECTS.md

no changes added to commit (use "git add" and/or "git commit -a")

Затем, если вы выполните команду git rm, удаление файла попадёт в индекс:

$ git rm PROJECTS.md
rm 'PROJECTS.md'
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    PROJECTS.md

После следующего коммита файл исчезнет и больше не будет отслеживаться.
Если вы изменили файл и уже проиндексировали его, вы должны использовать принудительное удаление с помощью параметра -f.
Это сделано для повышения безопасности, чтобы предотвратить ошибочное удаление данных, которые ещё не были записаны в снимок состояния и которые нельзя восстановить из Git.

Другая полезная штука, которую вы можете захотеть сделать — это удалить файл из индекса, оставив его при этом в рабочем каталоге.
Другими словами, вы можете захотеть оставить файл на жёстком диске, но перестать отслеживать изменения в нём.
Это особенно полезно, если вы забыли добавить что-то в файл .gitignore и по ошибке проиндексировали, например, большой файл с логами, или кучу промежуточных файлов компиляции.
Чтобы сделать это, используйте опцию --cached:

В команду git rm можно передавать файлы, каталоги или шаблоны.
Это означает, что вы можете сделать что-то вроде:

Обратите внимание на обратный слеш () перед *.
Он необходим из-за того, что Git использует свой собственный обработчик имён файлов вдобавок к обработчику вашего командного интерпретатора.
Эта команда удаляет все файлы, имеющие расширение .log и находящиеся в каталоге log/.
Или же вы можете сделать вот так:

Эта команда удаляет все файлы, имена которых заканчиваются на ~.

Перемещение файлов

В отличие от многих других систем контроля версий, Git не отслеживает перемещение файлов явно.
Когда вы переименовываете файл в Git, в нём не сохраняется никаких метаданных, говорящих о том, что файл был переименован.
Однако, Git довольно умён в плане обнаружения перемещений постфактум — мы рассмотрим обнаружение перемещения файлов чуть позже.

Таким образом, наличие в Git команды mv выглядит несколько странным.
Если вам хочется переименовать файл в Git, вы можете сделать что-то вроде:

$ git mv file_from file_to

и это отлично сработает.
На самом деле, если вы выполните что-то вроде этого и посмотрите на статус, вы увидите, что Git считает, что произошло переименование файла:

$ git mv README.md README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

Однако, это эквивалентно выполнению следующих команд:

$ mv README.md README
$ git rm README.md
$ git add README

Git неявно определяет, что произошло переименование, поэтому неважно, переименуете вы файл так или используя команду mv.
Единственное отличие состоит лишь в том, что mv — одна команда вместо трёх — это функция для удобства.
Важнее другое — вы можете использовать любой удобный способ для переименования файла, а затем воспользоваться командами add или rm перед коммитом.

vedro-compota's picture

Файл .gitignore может не работать в случае, если клонированный вами репозиторий уже содержал правила для файлов и папок которые вы пытаетесь исключить (то есть они не были в .gitignore и не игнорировались — а вы резко захотели их игнорировать) — в этом случае внесение их в файл игнорирования само по не поможет — их нужно удалить из «контроля»

Что делать

-прейдите в папку с кодом (ваш локальный репозиторий) :

и удалите файл из контроля (например .htaccess):

Аналогично можно заставить игнорировать и сам .gitignore (если раньше не игнорировался):

Потом делаем Commit и ярлыки (если они есть — например в винде с использованием tortoisegit) покажут нам что удалённые из кэша файлы теперь игнорируются.

На основании документации по git:

.gitignore

If you create a file in your repository named .gitignore git will use its rules when looking at
files to commit. Note that git will not ignore a file that was already tracked before a rule was added to this file to ignore it. In such a case the file must be un-tracked, usually with
git rm —cached filename

Не игнорируются файлы в .gitignore

Читаю книгу Test-Driven Development with Python, во второй главе описывается создание git-репозитория. Я следую всем инструкциям, но мой файл .gitignore не игнорирует записанное в нём. В чём проблема?

pic

user avatar

user avatar

Подозреваю, что вы добавили файлы в индекс раньше, чем начали игнорировать. То есть до той git add . , который на скриншоте, была еще одна такая команда. Чтобы узнать точно, не хватает git status перед добавлением.

Если файл уже был добавлен, то изменение в .gitignore не вызывает удаления из текущего индекса (что логично и безопасно).

Если файлы только добавлены, но еще не включены в коммит

В данном конкретном случае именно так и есть. При этом достаточно удалить их из индекса. Данная команда возвращает индекс к HEAD, то есть состоянию последнего коммита.

Вы можете заметить, что сам Git предлагает использовать другую команду:

В данном случае эти команды эквивалентны. Такое дублирование появилось в результате эволюционного развития функционала Git. Это в том числе отражено в документации и в сообщениях Git: где-то рекомендуется reset , где-то rm —cached .

Если игнорируемые файлы уже есть в последнем коммите

Возможна и такая ситуация, на всякий случай я опишу и ее. Здесь reset не сработает, нужен rm . Аргумент —cached заставляет Git удалить файл из индекса, но не трогать рабочую область. То есть он буквально индексирует удаление файла, хотя этого удаления не было. Если сделать это с файлом, который не игнорируется, то после коммита он будет в категории неотслеживаемых (untracked).

Если нужно убрать целую игнорируемую папку, добавляем ключ -r:

Эта удобная команда применяет rm ко всем файлам, указанным в .gitignore :

Вступление

В этом разделе показано, как избежать добавления нежелательных файлов (или изменений файлов) в репозитории Git. Существует несколько способов (глобальный или локальный .gitignore , .git/exclude , git update-index --assume-unchanged и git update-index --skip-tree ), но имейте в виду, что Git управляет контентом , что означает: игнорирование фактически игнорирует содержимое папки (то есть файлы). По умолчанию пустая папка будет проигнорирована, так как она не может быть добавлена ​​в любом случае.

Игнорирование файлов и каталогов с помощью файла .gitignore

Вы можете заставить Git игнорировать определенные файлы и каталоги, то есть исключить их от отслеживания Git — путем создания одного или нескольких файлов .gitignore в вашем репозитории.

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

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

При создании в каталоге верхнего уровня правила будут применяться рекурсивно ко всем файлам и подкаталогам во всем репозитории. При создании в подкаталоге правила будут применяться к этому конкретному каталогу и его подкаталогам.

Когда файл или каталог игнорируются, это не будет:

  1. отслеживается Git
  2. сообщается командами, такими как git status или git diff
  3. с такими командами, как git add -A

В необычном случае, когда вам нужно игнорировать отслеживаемые файлы, следует соблюдать особую осторожность. См .: Игнорировать файлы, которые уже были переданы в репозиторий Git .


Примеры

Вот некоторые общие примеры правил в файле .gitignore , основанные на шаблонах файлов glob :

# Lines starting with `#` are comments.

# Ignore files called 'file.ext'
file.ext

# Comments can't be on the same line as rules!
# The following line ignores files called 'file.ext # not a comment'
file.ext # not a comment 

# Ignoring files with full path.
# This matches files in the root directory and subdirectories too.
# i.e. otherfile.ext will be ignored anywhere on the tree.
dir/otherdir/file.ext
otherfile.ext

# Ignoring directories
# Both the directory itself and its contents will be ignored.
bin/
gen/

# Glob pattern can also be used here to ignore paths with certain characters.
# For example, the below rule will match both build/ and Build/
[bB]uild/

# Without the trailing slash, the rule will match a file and/or
# a directory, so the following would ignore both a file named `gen`
# and a directory named `gen`, as well as any contents of that directory
bin
gen

# Ignoring files by extension
# All files with these extensions will be ignored in
# this directory and all its sub-directories.
*.apk
*.class

# It's possible to combine both forms to ignore files with certain
# extensions in certain directories. The following rules would be
# redundant with generic rules defined above.
java/*.apk
gen/*.class

# To ignore files only at the top level directory, but not in its
# subdirectories, prefix the rule with a `/`
/*.apk
/*.class

# To ignore any directories named DirectoryA 
# in any depth use ** before DirectoryA
# Do not forget the last /, 
# Otherwise it will ignore all files named DirectoryA, rather than directories
**/DirectoryA/
# This would ignore 
# DirectoryA/
# DirectoryB/DirectoryA/ 
# DirectoryC/DirectoryB/DirectoryA/
# It would not ignore a file named DirectoryA, at any level

# To ignore any directory named DirectoryB within a 
# directory named DirectoryA with any number of 
# directories in between, use ** between the directories
DirectoryA/**/DirectoryB/
# This would ignore 
# DirectoryA/DirectoryB/ 
# DirectoryA/DirectoryQ/DirectoryB/ 
# DirectoryA/DirectoryQ/DirectoryW/DirectoryB/

# To ignore a set of files, wildcards can be used, as can be seen above.
# A sole '*' will ignore everything in your folder, including your .gitignore file.
# To exclude specific files when using wildcards, negate them.
# So they are excluded from the ignore list:
!.gitignore 

# Use the backslash as escape character to ignore files with a hash (#)
# (supported since 1.6.2.1)
#*#

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


Другие формы .gitignore

Файлы .gitignore предназначены для передачи как часть репозитория. Если вы хотите игнорировать определенные файлы без соблюдения правил игнорирования, вот несколько вариантов:

  • Отредактируйте файл .git/info/exclude (используя тот же синтаксис, что и .gitignore ). Правила будут глобальными в объеме хранилища;
  • Настройте глобальный файл gitignore, который будет применять правила игнорирования ко всем вашим локальным репозиториям:

Кроме того, вы можете игнорировать локальные изменения в отслеживаемых файлах без изменения глобальной конфигурации git с помощью:

  • git update-index --skip-worktree [<file>...] : для небольших локальных изменений
  • git update-index --assume-unchanged [<file>...] : для производства готовые, не изменяющиеся файлы вверх по течению

Подробнее о различиях между последними флагами и документации по git update-index см. Подробнее .


Очистка игнорируемых файлов

Вы можете использовать git clean -X для очистки игнорируемых файлов:

git clean -Xn #display a list of ignored files
git clean -Xf #remove the previously displayed files

Примечание: -X (caps) очищает только игнорируемые файлы. Используйте -x (без ограничений), чтобы удалить ненужные файлы.

Подробнее см. Документацию git clean .


Дополнительную информацию см. В руководстве Git .

Исключения в файле .gitignore

Если вы игнорируете файлы с помощью шаблона, но имеете исключения, префикс восклицательного знака (!) К исключению. Например:

*.txt
!important.txt

В приведенном выше примере Git игнорирует все файлы с расширением .txt за исключением файлов с именем important.txt .

Если файл находится в папке проигнорировано, вы не можете повторно включить его так легко:

folder/
!folder/*.txt

В этом примере все .txt-файлы в папке будут игнорироваться.

Правильный способ заключается в повторном включении самой папки в отдельной строке, а затем игнорировать все файлы в folder на * , наконец, повторно включить *.txt в folder , как показано ниже:

!folder/
folder/*
!folder/*.txt

Примечание . Для имен файлов, начинающихся с восклицательного знака, добавьте два восклицательных знака или выйдите с символом :

!!includethis
!excludethis

Глобальный файл .gitignore

Чтобы Git игнорировал определенные файлы во всех репозиториях, вы можете создать глобальный .gitignore со следующей командой в своем терминале или командной строке:

$ git config --global core.excludesfile <Path_To_Global_gitignore_file>

Теперь Git будет использовать это в дополнение к собственному файлу .gitignore каждого репозитория. Правила для этого:

  • Если локальный файл .gitignore явно содержит файл, а глобальный .gitignore игнорирует его, локальный .gitignore имеет приоритет (файл будет включен)
  • Если репозиторий клонирован на нескольких компьютерах, глобальный .gigignore должен быть загружен на всех машинах или, по крайней мере, включать его, поскольку проигнорированные файлы будут .gitignore на репо, тогда как ПК с глобальным .gitignore не будет обновлять его , Вот почему специфический .gitignore — лучшая идея, чем глобальная, если проект обрабатывается командой

Этот файл является хорошим местом для игнорирования игнорирования .DS_Store платформы, компьютера или пользователя, например OSX .DS_Store , Windows Thumbs.db или Vim *.ext~ и *.ext.swp игнорирует, если вы не хотите сохранять их в репозитории , Поэтому один член команды, работающий над OS X, может добавить все .DS_STORE и _MACOSX (что фактически бесполезно), в то время как другой член команды в Windows может игнорировать все thumbs.bd

Если вы уже добавили файл в свой репозиторий Git и теперь хотите прекратить его отслеживать (чтобы он не присутствовал в будущих коммитах), вы можете удалить его из индекса:

git rm --cached <file>

Это приведет к удалению файла из репозитория и предотвращению отслеживания дальнейших изменений Git. Параметр --cached гарантирует, что файл не будет физически удален.

Обратите внимание, что ранее добавленное содержимое файла по-прежнему будет отображаться через историю Git.

Имейте в виду, что если кто-то еще вытащит из репозитория после удаления файла из индекса, их копия будет физически удалена .


Вы можете заставить Git притвориться, что версия рабочего каталога файла обновлена ​​и вместо этого прочитала индексную версию (таким образом, игнорируя изменения в ней) с битом « skip worktree »:

git update-index --skip-worktree <file>

На этот бит не влияет запись, безопасность контента по-прежнему является первоочередной задачей. Вы никогда не потеряете свои драгоценные игнорируемые изменения; с другой стороны, этот бит конфликтует с тиснением: чтобы удалить этот бит, используйте

git update-index --no-skip-worktree <file>

Иногда ошибочно рекомендуется лгать Гиту и предположить, что файл остается неизменным, не изучая его. Он выглядит на первый взгляд как игнорирование любых дальнейших изменений в файле, не удаляя его из его индекса:

git update-index --assume-unchanged <file>

Это заставит git игнорировать любые изменения, внесенные в файл (имейте в виду, что если вы поместите какие-либо изменения в этот файл или вы его запишете, ваши проигнорированные изменения будут потеряны )

Если вы хотите, чтобы git снова «заботился» об этом файле, выполните следующую команду:

git update-index --no-assume-unchanged <file>

Проверка игнорирования файла

Команда git check-ignore сообщает о файлах, игнорируемых Git.

Вы можете передавать имена файлов в командной строке, а git check-ignore будет отображать имена файлов, которые игнорируются. Например:

$ cat .gitignore
*.o
$ git check-ignore example.o Readme.md
example.o

Здесь только * .o файлы определены в .gitignore, поэтому Readme.md не указан в выводе git check-ignore .

Если вы хотите увидеть строку, в которой .gitignore отвечает за игнорирование файла, добавьте -v в команду git check-ignore:

$ git check-ignore -v example.o Readme.md
.gitignore:1:*.o        example.o

Начиная с Git 1.7.6, вы также можете использовать git status --ignored , чтобы увидеть проигнорированные файлы. Дополнительную информацию об этом можно найти в официальной документации или в разделе «Поиск файлов, игнорируемых с помощью .gitignore» .

Игнорирование файлов в подпапках (несколько файлов gitignore)

Предположим, что у вас есть структура репозитория:

examples/
    output.log
src/
    <files not shown>
    output.log
README.md

output.log в каталоге примеров действителен и требуется, чтобы проект собирал понимание, в то время как один под src/ создается во время отладки и не должен находиться в истории или части хранилища.

Существует два способа игнорировать этот файл. Вы можете поместить абсолютный путь в файл .gitignore в корень рабочего каталога:

# /.gitignore
src/output.log

Кроме того, вы можете создать файл .gitignore каталоге src/ и проигнорировать файл, относящийся к этому .gitignore :

# /src/.gitignore
output.log

Игнорирование файла в любом каталоге

Чтобы игнорировать файл foo.txt в любом каталоге, вы должны просто написать его имя:

foo.txt # matches all files 'foo.txt' in any directory

Если вы хотите игнорировать файл только в части дерева, вы можете указать подкаталоги определенного каталога с ** pattern:

bar/**/foo.txt # matches all files 'foo.txt' in 'bar' and all subdirectories

Или вы можете создать файл .gitignore каталоге bar/ . Эквивалентным предыдущему примеру будет создание файла bar/.gitignore с этим содержимым:

foo.txt # matches all files 'foo.txt' in any directory under bar/

Игнорировать файлы локально без правил игнорирования

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

Если вы хотите игнорировать определенные файлы в репозитории локально и не создавать файловую часть какого-либо репозитория, отредактируйте файл .git/info/exclude внутри своего репозитория.

Например:

# these files are only ignored on this repo
# these rules are not shared with anyone
# as they are personal                                              
gtk_tests.py
gui/gtk/tests/*
localhost
pushReports.py
server/

Заполненные шаблоны .gitignore

Если вы не знаете, какие правила перечислять в вашем файле .gitignore или просто хотите добавить общепринятые исключения в свой проект, вы можете выбрать или сгенерировать файл .gitignore :

  • https://www.toptal.com/developers/gitignore
  • https://github.com/github/gitignore

Многие хостинговые сервисы, такие как GitHub и BitBucket, предлагают возможность генерации файлов .gitignore на основе языков программирования и IDE, которые вы можете использовать:

Выпадающее меню GitHub .gitignore

Игнорирование последующих изменений в файле (без его удаления)

Иногда вы хотите иметь файл, хранящийся в Git, но игнорировать последующие изменения.

Скажите Git игнорировать изменения в файле или каталоге с помощью update-index :

git update-index --assume-unchanged my-file.txt

Вышеупомянутая команда дает указание Git предположить, my-file.txt не был изменен, а не проверять или сообщать об изменениях. Файл все еще присутствует в репозитории.

Это может быть полезно для предоставления значений по умолчанию и разрешения переопределения локальной среды, например:

# create a file with some values in
cat <<EOF
MYSQL_USER=app
MYSQL_PASSWORD=FIXME_SECRET_PASSWORD
EOF > .env

# commit to Git
git add .env
git commit -m "Adding .env template"

# ignore future changes to .env
git update-index --assume-unchanged .env

# update your password
vi .env

# no changes!
git status

Игнорирование только части файла [заглушки]

Иногда вам может потребоваться локальные изменения в файле, который вы не хотите комментировать или публиковать. В идеале локальные настройки должны быть сконцентрированы в отдельном файле, который может быть помещен в .gitignore , но иногда в качестве краткосрочного решения может быть полезно иметь что-то локальное в зарегистрированном файле.

Вы можете сделать Git «unsee» эти строки, используя чистый фильтр. Они даже не появятся в разностях.

Предположим, что это фрагмент файла file1.c :

struct settings s;
s.host = "localhost";
s.port = 5653;
s.auth = 1;
s.port = 15653; // NOCOMMIT
s.debug = 1; // NOCOMMIT
s.auth = 0; // NOCOMMIT

Вы не хотите публиковать NOCOMMIT .

Создайте фильтр «nocommit», добавив его в конфигурационный файл Git, например .git/config :

[filter "nocommit"]
    clean=grep -v NOCOMMIT

Добавьте (или создайте) это в .git/info/attributes или .gitmodules :

file1.c filter=nocommit

И ваши линии NOCOMMIT скрыты от Git.

Предостережения:

  • Использование чистого фильтра замедляет обработку файлов, особенно в Windows.
  • Пропущенная строка может исчезнуть из файла, когда Git обновляет ее. Его можно противодействовать фильтром размытия, но это сложнее.
  • Не тестировалось в Windows

Игнорирование изменений в отслеживаемых файлах. [Заглушка]

.gitignore и .git/info/exclude работают только для файлов без следа.

Чтобы установить флаг игнорирования в отслеживаемом файле, используйте команду update-index :

git update-index --skip-worktree myfile.c

Чтобы восстановить это, используйте:

git update-index --no-skip-worktree myfile.c

Вы можете добавить этот фрагмент в свою глобальную конфигурацию git, чтобы иметь более удобную git hidden git hide , git unhide и git hidden команды:

[alias]
    hide   = update-index --skip-worktree
    unhide = update-index --no-skip-worktree
    hidden  = "!git ls-files -v | grep ^[hsS] | cut -c 3-"

Вы также можете использовать опцию —assume-неизменной с функцией update-index

git update-index --assume-unchanged <file>

Если вы хотите снова просмотреть этот файл для изменений, используйте

git update-index --no-assume-unchanged <file>

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

Хотя флаг -skip-worktree полезен, когда вы даете указание git не касаться определенного файла из-за того, что файл будет изменен локально, и вы не захотите случайно зафиксировать изменения (т. Е. Файл конфигурации / свойств, сконфигурированный для определенного среда). Skip-worktree имеет приоритет над принятием-неизменным, когда оба установлены.

Очистить уже зафиксированные файлы, но включенные в .gitignore

Иногда случается, что файл отслеживается git, но в более поздний момент времени был добавлен в .gitignore, чтобы остановить его отслеживание. Очень распространенный сценарий забыть очистить такие файлы до его добавления в .gitignore. В этом случае старый файл все равно будет висящим в репозитории.

Чтобы устранить эту проблему, можно было выполнить «сухое» удаление всего в репозитории, а затем повторное добавление всех файлов обратно. Пока у вас нет ожидающих изменений и --cached параметр --cached , эта команда достаточно безопасна для запуска:

# Remove everything from the index (the files will stay in the file system) 
$ git rm -r --cached .

# Re-add everything (they'll be added in the current state, changes included)
$ git add .

# Commit, if anything changed. You should see only deletions
$ git commit -m 'Remove all files that are in the .gitignore'

# Update the remote
$ git push origin master

Создать пустую папку

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

Метод первый: .gitkeep

Один хак, чтобы обойти это, — использовать файл .gitkeep для регистрации папки для Git. Для этого просто создайте требуемый каталог и добавьте файл .gitkeep в папку. Этот файл пуст и не служит никакой другой цели, кроме как просто зарегистрировать эту папку. Для этого в Windows (который имеет неудобные соглашения об именах файлов) просто запустите git bash в каталоге и запустите команду:

$ touch .gitkeep

Эта команда просто делает пустой файл .gitkeep в текущем каталоге

dummy.txt способ: dummy.txt

Другой взлом для этого очень похож на выше, и те же шаги могут быть выполнены, но вместо .gitkeep просто используйте вместо него dummy.txt . Это дает дополнительный бонус, позволяющий легко создавать его в Windows с помощью контекстного меню. И вы также можете оставить в них смешные сообщения. Вы также можете использовать файл .gitkeep для отслеживания пустого каталога. .gitkeep обычно представляет собой пустой файл, который добавляется для отслеживания пустой строки.

Поиск файлов, игнорируемых .gitignore

Вы можете перечислить все файлы, игнорируемые git в текущем каталоге командой:

git status --ignored

Итак, если у нас есть структура репозитория, вот так:

.git
.gitignore
./example_1
./dir/example_2
./example_2

… и .gitignore файл, содержащий:

example_2

… чем результат команды будет:

$ git status --ignored

On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

.gitignore
.example_1

Ignored files:
  (use "git add -f <file>..." to include in what will be committed)

dir/
example_2

Если вы хотите перечислить рекурсивно проигнорированные файлы в каталогах, вам нужно использовать дополнительный параметр — --untracked-files=all

Результат будет выглядеть так:

$ git status --ignored --untracked-files=all
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

.gitignore
example_1

Ignored files:
  (use "git add -f <file>..." to include in what will be committed)

dir/example_2
example_2

I have the folder application/ which I add to the .gitignore. Inside the application/ folder is the folder application/language/gr. How can I include this folder?

I’ve tried this

application/
!application/language/gr/

LinFelix's user avatar

LinFelix

7611 gold badge14 silver badges23 bronze badges

asked Apr 3, 2011 at 22:48

chchrist's user avatar

3

If you exclude application/, then everything under it will always be excluded (even if some later negative exclusion pattern (“unignore”) might match something under application/).

To do what you want, you have to “unignore” every parent directory of anything that you want to “unignore”. Usually you end up writing rules for this situation in pairs: ignore everything in a directory, but not some certain subdirectory.

# you can skip this first one if it is not already excluded by prior patterns
!application/

application/*
!application/language/

application/language/*
!application/language/gr/

Note
The trailing /* is significant:

  • The pattern dir/ excludes a directory named dir and (implicitly) everything under it.
    With dir/, Git will never look at anything under dir, and thus will never apply any of the “un-exclude” patterns to anything under dir.
  • The pattern dir/* says nothing about dir itself; it just excludes everything under dir.
    With dir/*, Git will process the direct contents of dir, giving other patterns a chance to “un-exclude” some bit of the content (!dir/sub/).

fawaad's user avatar

fawaad

3415 silver badges12 bronze badges

answered Apr 4, 2011 at 5:22

Chris Johnsen's user avatar

Chris JohnsenChris Johnsen

209k26 gold badges206 silver badges185 bronze badges

16

Commit 59856de from Karsten Blees (kblees) for Git 1.9/2.0 (Q1 2014) clarifies that case:

gitignore.txt: clarify recursive nature of excluded directories

An optional prefix «!» which negates the pattern; any matching file excluded by a previous pattern will become included again.

It is not possible to re-include a file if a parent directory of that file is excluded. (*)
(*: unless certain conditions are met in git 2.8+, see below)
Git doesn’t list excluded directories for performance reasons, so any patterns on contained files have no effect, no matter where they are defined.

Put a backslash (««) in front of the first «!» for patterns that begin with a literal «!«, for example, «!important!.txt«.

Example to exclude everything except a specific directory foo/bar (note the /* — without the slash, the wildcard would also exclude everything within foo/bar):

 --------------------------------------------------------------
     $ cat .gitignore
     # exclude everything except directory foo/bar
     /*
     !/foo
     /foo/*
     !/foo/bar
 --------------------------------------------------------------

In your case:

application/*
!application/**/
application/language/*
!application/language/**/
!application/language/gr/**

You must white-list folders first, before being able to white-list files within a given folder.


Update Feb/March 2016:

Note that with git 2.9.x/2.10 (mid 2016?), it might be possible to re-include a file if a parent directory of that file is excluded if there is no wildcard in the path re-included.

Nguyễn Thái Ngọc Duy (pclouds) is trying to add this feature:

  • commit 506d8f1 for git v2.7.0, reverted in commit 76b620d git v2.8.0-rc0
  • commit 5e57f9c git v2.8.0-rc0,… reverted(!) in commit 5cee3493 git 2.8.0.

So with git 2.9+, this could have actually worked, but was ultimately reverted:

application/
!application/language/gr/

answered Dec 18, 2013 at 8:10

VonC's user avatar

VonCVonC

1.2m508 gold badges4248 silver badges5069 bronze badges

8

@Chris Johnsen’s answer is great, but with a newer versions of Git (1.8.2 or later), there is a double asterisk pattern you can leverage for a bit more shorthand solution:

# assuming the root folder you want to ignore is 'application'
application/**/*

# the subfolder(s) you want to track:
!application/language/gr/

This way you don’t have to «unignore» parent directory of the subfolder you want to track.


With Git 2.17.0 (Not sure how early before this version. Possibly back to 1.8.2), using the ** pattern combined with excludes for each subdirectory leading up to your file(s) works. For example:

# assuming the root folder you want to ignore is 'application'
application/**

# Explicitly track certain content nested in the 'application' folder:
!application/language/
!application/language/gr/
!application/language/gr/** # Example adding all files & folder in the 'gr' folder
!application/language/gr/SomeFile.txt # Example adding specific file in the 'gr' folder

Ben Kane's user avatar

Ben Kane

9,0516 gold badges35 silver badges58 bronze badges

answered Sep 9, 2013 at 16:30

rpyzh's user avatar

rpyzhrpyzh

8876 silver badges9 bronze badges

4

I’ve found only this actually works.

**/node_modules/*
!**/node_modules/keep-dir

answered Feb 16, 2017 at 21:53

Steve Kling's user avatar

Steve KlingSteve Kling

4614 silver badges3 bronze badges

0

There are a bunch of similar questions about this, so I’ll post what I wrote before:

The only way I got this to work on my machine was to do it this way:

# Ignore all directories, and all sub-directories, and it's contents:
*/*

#Now ignore all files in the current directory 
#(This fails to ignore files without a ".", for example 
#'file.txt' works, but 
#'file' doesn't):
*.*

#Only Include these specific directories and subdirectories:
!wordpress/
!wordpress/*/
!wordpress/*/wp-content/
!wordpress/*/wp-content/themes/
!wordpress/*/wp-content/themes/*
!wordpress/*/wp-content/themes/*/*
!wordpress/*/wp-content/themes/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*/*

Notice how you have to explicitly allow content for each level you want to include. So if I have subdirectories 5 deep under themes, I still need to spell that out.

This is from @Yarin’s comment here: https://stackoverflow.com/a/5250314/1696153

These were useful topics:

  • How do negated patterns work in .gitignore?
  • How do gitignore exclusion rules actually work?

I also tried

*
*/*
**/**

and **/wp-content/themes/**

or /wp-content/themes/**/*

None of that worked for me, either. Lots of trial and error!

answered Apr 29, 2015 at 23:37

Katie's user avatar

KatieKatie

44.2k18 gold badges93 silver badges122 bronze badges

2

The simplest and probably best way is to try adding the files manually (generally this takes precedence over .gitignore-style rules):

git add /path/to/module

You might need -f if the file is already ignored. You may even want the -N intent to add flag, to suggest you will add them, but not immediately. I often do this for new files I’m not ready to stage yet.


This a copy of an answer posted on what could easily be a duplicate QA. I am reposting it here for increased visibility—I find it easier not to have a mess of gitignore rules.

answered Jun 7, 2019 at 12:52

D. Ben Knoble's user avatar

D. Ben KnobleD. Ben Knoble

4,1231 gold badge22 silver badges38 bronze badges

0

I have found a similar case here, where in laravel by default, .gitignore ignores all using asterix, then overrides the public directory.
( This is also the same solution as the main answer @Chris Johnsen, just a bit thinner and more concise maybe.)

*
!public
!.gitignore

This is not sufficient if you run into the OP scenario.

If you want to commit a specific subfolders of public, say for e.g. in your public/products directory you want to include files that are one subfolder deep e.g. to include public/products/a/b.jpg they wont be detected correctly, even if you add them specifically like this !/public/products, !public/products/*, etc..

The solution is to make sure you add an entry for every path level like this to override them all.

*
!.gitignore
!public/
!public/*/
!public/products/
!public/products/*
!public/products/*/
!public/products/*/
!public/products/*/*

answered Oct 21, 2017 at 1:43

blamb's user avatar

blambblamb

4,1824 gold badges31 silver badges50 bronze badges

I wanted to track Nagios configuration files located in /etc/nagios/ together with the plugins in /usr/lib64/nagios/plugins/. For this I have initialized a git repo in / and used the following exclusion list:

/*
!etc
etc/*
!etc/nagios
!usr
usr/*
!usr/lib64
usr/lib64/*
!usr/lib64/nagios
usr/lib64/nagios/*
!usr/lib64/nagios/plugins

Git walks down the list like that:

/*             exclude everything under / ...
!etc           but include /etc back
etc/*             exclude everything under /etc/...
!etc/nagios       but include /etc/nagios back
!usr           but include /usr back
usr/*             exclude everything under /usr/...
                  and so on...

answered Aug 25, 2021 at 10:40

BMC's user avatar

BMCBMC

1542 silver badges9 bronze badges

add a file named .gitignore to subfolder, then fill with

!/Bin/

this works for me!

answered Sep 26, 2021 at 6:32

jiayi797's user avatar

jiayi797jiayi797

1411 silver badge4 bronze badges

So , since many programmers uses node . the use case which meets this question is to exclude node_modules except one module module-a for example:

!node_modules/

node_modules/*
!node_modules/module-a/

answered Sep 1, 2016 at 21:19

Abdennour TOUMI's user avatar

Abdennour TOUMIAbdennour TOUMI

83.1k37 gold badges237 silver badges246 bronze badges

2

Add an additional answer:

!/.vs/              <== include this folder to source control, folder only, nothing else
/.vs/*              <== but ignore all files and sub-folder inside this folder
!/.vs/ProjectSettings.json <== but include this file to source control
!/.vs/config/       <== then include this folder to source control, folder only, nothing else
!/.vs/config/*      <== then include all files inside the folder

here is result:

enter image description here

answered Dec 6, 2018 at 16:39

Dongdong's user avatar

DongdongDongdong

2,09017 silver badges26 bronze badges

0

This worked for me:

**/.idea/**
!**/.idea/copyright/
!.idea/copyright/profiles_settings.xml
!.idea/copyright/Copyright.xml

answered Jul 27, 2020 at 6:45

garbo's user avatar

garbogarbo

1392 silver badges2 bronze badges

1

Especially for the older Git versions, most of the suggestions won’t work that well.
If that’s the case, I’d put a separate .gitignore in the directory where I want the content to be included regardless of other settings and allow there what is needed.

For example:
/.gitignore

# ignore all .dll files
*.dll

/dependency_files/.gitignore

# include everything
!*

So everything in /dependency_files (even .dll files) are included just fine.

answered Apr 6, 2017 at 9:37

Breit's user avatar

BreitBreit

3795 silver badges9 bronze badges

In WordPress, this helped me:

wp-admin/
wp-includes/
/wp-content/*
!wp-content/plugins/
/wp-content/plugins/*
!/wp-content/plugins/plugin-name/
!/wp-content/plugins/plugin-name/*.*
!/wp-content/plugins/plugin-name/**

answered May 21, 2018 at 15:44

T.Todua's user avatar

T.ToduaT.Todua

51.2k19 gold badges224 silver badges225 bronze badges

gitignore — Specifies intentionally untracked files to ignore.

Example to exclude everything except a specific directory foo/bar (note the /* — without the slash, the wildcard would also exclude everything within foo/bar):

$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/bar

Another example for WordPress:

!/wp-content
wp-content/*
!/wp-content/plugins
wp-content/plugins/*
!wp-content/plugins/my-awesome-plugin

More informations in here: https://git-scm.com/docs/gitignore

answered Dec 24, 2018 at 3:12

Ali Han's user avatar

Ali HanAli Han

4595 silver badges10 bronze badges

Just another example of walking down the directory structure to get exactly what you want. Note: I didn’t exclude Library/ but Library/**/*

# .gitignore file
Library/**/*
!Library/Application Support/
!Library/Application Support/Sublime Text 3/
!Library/Application Support/Sublime Text 3/Packages/
!Library/Application Support/Sublime Text 3/Packages/User/
!Library/Application Support/Sublime Text 3/Packages/User/*macro
!Library/Application Support/Sublime Text 3/Packages/User/*snippet
!Library/Application Support/Sublime Text 3/Packages/User/*settings
!Library/Application Support/Sublime Text 3/Packages/User/*keymap
!Library/Application Support/Sublime Text 3/Packages/User/*theme
!Library/Application Support/Sublime Text 3/Packages/User/**/
!Library/Application Support/Sublime Text 3/Packages/User/**/*macro
!Library/Application Support/Sublime Text 3/Packages/User/**/*snippet
!Library/Application Support/Sublime Text 3/Packages/User/**/*settings
!Library/Application Support/Sublime Text 3/Packages/User/**/*keymap
!Library/Application Support/Sublime Text 3/Packages/User/**/*theme

> git add Library

> git status

On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   Library/Application Support/Sublime Text 3/Packages/User/Default (OSX).sublime-keymap
    new file:   Library/Application Support/Sublime Text 3/Packages/User/ElixirSublime.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/Package Control.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/Preferences.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/RESTer.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/SublimeLinter/Monokai (SL).tmTheme
    new file:   Library/Application Support/Sublime Text 3/Packages/User/TextPastryHistory.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/ZenTabs.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/adrian-comment.sublime-macro
    new file:   Library/Application Support/Sublime Text 3/Packages/User/json-pretty-generate.sublime-snippet
    new file:   Library/Application Support/Sublime Text 3/Packages/User/raise-exception.sublime-snippet
    new file:   Library/Application Support/Sublime Text 3/Packages/User/trailing_spaces.sublime-settings

answered Sep 14, 2016 at 14:53

Adrian Dunston's user avatar

Adrian DunstonAdrian Dunston

2,9404 gold badges24 silver badges23 bronze badges

0

Similar to this comment, none of the solutions and patterns worked for me; forcing git to add the files and folders that should be excluded, worked:

git add -f .

answered Jun 23, 2022 at 16:14

nightblade9's user avatar

nightblade9nightblade9

3442 silver badges14 bronze badges

I wanted to track jquery production js files and this worked:

node_modules/*
!node_modules/jquery
node_modules/jquery/*
!node_modules/jquery/dist/*

answered Mar 30, 2018 at 6:58

I often use this workaround in CLI where instead of configuring my .gitignore, I create a separate .include file where I define the (sub)directories I want included in spite of directories directly or recursively ignored by .gitignore.

Thus, I additionally use

git add `cat .include`

during staging, before committing.

To the OP, I suggest using a .include which has these lines:

<parent_folder_path>/application/language/gr/*

NOTE: Using cat does not allow usage of aliases (within .include) for specifying $HOME (or any other specific directory). This is because the line homedir/app1/*
when passed to git add using the above command appears as git add 'homedir/app1/*', and enclosing characters in single quotes (») preserves the literal value of each character within the quotes, thus preventing aliases (such as homedir) from functioning (see Bash Single Quotes).

Here is an example of a .include file I use in my repo here.

/home/abhirup/token.txt
/home/abhirup/.include
/home/abhirup/.vim/*
/home/abhirup/.viminfo
/home/abhirup/.bashrc
/home/abhirup/.vimrc
/home/abhirup/.condarc

answered Dec 3, 2018 at 9:47

Abhirup Das's user avatar

Abhirup DasAbhirup Das

6435 silver badges8 bronze badges

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Git xcrun error invalid active developer path
  • Git submodule error pathspec
  • Git remote https symbol lookup error
  • Git remote error refusing to update checked out branch
  • Git rebase error

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии