Файлы миграций Django для большого проекта в git (Лучшая практика)
Я работаю с командой в проекте Django, в локальном git с той же базой данных. Мы обнаружили, что есть много проблем с миграциями django, особенно когда команда большая.
Поэтому мы решили сделать базы данных для каждого разработчика, иногда разработчик удаляет файлы миграций, чтобы решить некоторые проблемы с миграциями.
мы получаем много конфликтов в файлах миграций Django, мы решили добавить файлы миграций в gitignore.
После этого вся работа стала более гладкой. но у нас возникли некоторые проблемы, мы потеряли историю git для файлов миграций, это создает проблемы при обновлении версий проекта из определенного тега git. Также, это удаляет файлы миграций каждый раз, когда мы делаем "checkout" в git.
Я предложил следующее, но нашел ответы
make migrations files tracked by local repository and ignored in remote repository.
Кто-нибудь сталкивался с этой проблемой?
На вопрос о том, следует ли фиксировать файлы миграции, достаточно хорошо отвечает ссылка на возможный дубликат. Этот ответ не об этом: он о предложенном вами решении.
Идея сделать какой-то файл "отслеживаемым" каким-то конкретным хранилищем несколько бессмысленна. В Git'е файл отслеживается тогда и только тогда, когда этот файл находится в настоящее время в индексе Git'а. Следовательно, нам необходимо решить этот вопрос:
Когда файл попадает в индекс Git'а?
Простой ответ прост - слишком прост, запутан и бесполезен: файл находится в индексе Git'а, когда этот файл находится в индексе Git'а. Однако файлы постоянно входят и выходят из индекса Git'а.
Цель индекса в Git'е - помочь вам создать следующий коммит, который вы сделаете. Файлы, которые находятся в индексе Git'а прямо сейчас - и это меняется от одного момента времени к другому - это файлы, которые будут находиться в вашем следующем коммите.
The git add
command will, under the right conditions, copy a file from your working tree—the files you can see and work on / with are in your working tree—to Git's index. If there was already some file with that name in Git's index, that copy is kicked out of the index, so that the working tree copy can be copied in. If there was no file with that name in Git's index, the file is now added to Git's index. This copy, once copied into Git's index, remains there, in Git's index, even if you change or remove the working tree copy: these are separate copies.1
При других условиях git add
ничего не сделает или даже удалит индексную копию файла. Использование git rm --cached
приведет к удалению индексной копии файла, а использование git rm
приведет к удалению как индексной копии, так и копии рабочего дерева. Таким образом, у вас есть несколько команд Git, которые могут повлиять на индексную копию: git add
, которая может заменить индексную копию или удалить ее, и git rm
, которая может удалить ее.
Условия, при которых git add
делает каждую из этих вещей, немного сложны, но предназначены для того, чтобы было просто использовать:
git add
абсолютно нового файла добавляет его в индекс Git'а;git add
обновленного в рабочем дереве файла удаляет старую копию и добавляет новую; иgit add
файла удаленного - того, который вы удалили из рабочего дерева, но без использованияgit rm
для этого - удаляет индексную копию.
Итак, git add
"означает" заставить индексную копию соответствовать копии рабочего дерева.
Условие, при котором git add
делает ничего (кроме, возможно, выдачи предупреждения о том, что он не добавляет файл), возникает, когда файл (a) не уже находится в индексе и (b) перечислен в списке .gitignore
. Условие (b) означает не добавлять файл, даже если я скажу вам добавить его. Это не влияет на файл, который находится в индексе - см. условие (a)- потому что, ну, файл находится в индексе. Как бы он туда ни попал, он там сейчас , поэтому git add
обновит его, чтобы он соответствовал рабочему дереву.
Но есть еще один ключевой способ попадания файлов в индекс Git'а: всякий раз, когда вы извлекаете (git checkout
или git switch
) весь коммит, Git считывает коммит в индекс как часть извлечения файлов коммита в ваше рабочее дерево. Это означает, что проверка коммита, содержащего файл миграции, поместит этот файл в индекс Git'а. Коммиты контролируют, какие файлы будут <входить в индекс.
Коммиты - это то, что совместно используют два репозитория Git, когда вы соединяете их с помощью git fetch
, git pull
и/или git push
. Коммит, однажды сделанный, никогда не может быть изменен никаким образом . Таким образом, если кто-то, кто угодно, когда-либо зафиксировал некоторый файл миграции, и вы git checkout
зафиксировали этот файл, этот файл появится как в вашем рабочем дереве, так и в индексе Git'а. Если вы затем переключитесь с этого коммита, на какой-нибудь другой коммит, в котором этот файл отсутствует в коммите, Git удалит этот файл как из индекса Git'а, так и из вашего рабочего дерева.
<<<Переход от фиксации, в которой
есть файл, к фиксации, в которой нет файла, означает удаление файла. Переход от фиксации, в которой нет файла, к фиксации, в которой он есть, означает добавить файл. Это не является необязательным. Это происходит всегда, каждый раз. Файл попадает в индекс Git'а или выходит из него; теперь он отслеживается или не отслеживается соответственно.
Вы можете, перейдя к такому коммиту или от него, впоследствии изменить индекс Git'а, используя git add
и/или git rm
. Это изменит отслеживаемость файла. Но переход к другому коммиту или от него обновляет индекс Git'а, изменяя отслеживаемость файлов.
1 Копия индекса, однако, хранится в сжатом и де-дублированном формате Git'а, готовая к следующему коммиту. Это означает, что если вы воспользуетесь различными средствами отладки Git'а, чтобы найти внутренний объект и выгрузить его байты, они не будут совпадать с байтами копии рабочего дерева. Однако это схема сжатия без потерь, так что байты все на месте. Просто они могут занимать мало места на диске или даже вообще не занимать его из-за трюков сжатия и дедупликации, которые использует Git.
Итог
Вывод, который вы должны сделать из всего этого, заключается в том, что "отслеживаемость" файла не зависит от хранилища. Это зависит от индивидуального коммита. В каждом коммите есть несколько файлов. Извлечение этого коммита извлекает эти файлы, которые теперь отслеживаются. Каждый коммит не имеет некоторых других файлов. Извлечение этого коммита удалит эти файлы, если они находятся в вашем рабочем дереве, потому что они были извлечены из коммита, который удалял их.
Всё это контролируется содержимым индекса Git'а, поэтому возможно - но крайне болезненно - проверить какой-нибудь коммит, получив кучу отслеживаемых файлов, а затем с помощью удалить некоторые из этих файлов из индекса Git'а, чтобы Git забыл, что они появились в этом коммите. Переключение на какой-то git rm --cached
другой коммит, в котором отсутствуют эти файлы, оставит эти файлы в вашем рабочем дереве. Но многократное повторение этого действия чревато ошибками. Не делайте этого! Вы пожалеете об этом.