Git: игнорировать файлы для общего репозитория, но не для частных
Я развертываю приложение Rails на Heroku (на данный момент) через git, а также хотел бы иметь общедоступную версию для просмотра людьми. Некоторые файлы чувствительны и должны быть зафиксированы только в ветке "heroku", но не в "публичной" ветке. Каков наилучший способ сделать это?
(Я знаю переменные конфигурации Heroku, что отлично подходит для временного решения, но не весело, если и когда мне нужно переключать хосты.)
Два ветки не обязательно должны синхронизироваться в любое время - я согласен с периодическим слиянием ветки "master" в "общедоступную" ветвь и нажимаю ее на github отдельно.
Я пробовал разные вещи:
-
разделить файлы .gitignore
и стратегию слияния "наш" - это не сработало вначале, и после некоторого времени возиться с ним я решил, что он становится слишком сложным, чтобы я мог достичь, казалось бы, простого задача
-
с помощью пользовательского файла exclude
и добавления следующего в .git/config
... это просто не работает:
.git/конфигурации
[branch "public"]
excludesfile = +info/exclude_from_public
Каков наилучший способ совместного использования общего и общего репозитория одним и тем же кодом, но игнорировать чувствительные файлы в общедоступном хранилище?
Можно предположить, что никакой код не был зафиксирован или не нажат, т.е. это только что инициализированный репозиторий.
(Этот вопрос задавали раньше в различных формах, но ни один из ответов не был прямым, или ответы казались действительно взломанными. Я просто здесь, чтобы задать это очень просто, и, надеюсь, получить очень простой ответ.)
Ответы
Ответ 1
Я отвечу на вопрос о подмодуле, но попробую дать некоторое разъяснение. Во-первых, git не имеет дело с файлами, но с фиксацией. Невозможно фильтровать файлы или пути в ветке, потому что ветвь действительно является указателем на фиксацию. Когда вы исключаете или игнорируете, вы просто не добавляете файлы в свой репозиторий. ни один из файлов "чувствительных файлов" даже в репозитории не находится в вашем рабочем каталоге.
Подмодуль - это просто ссылка на другой репозиторий, хранящийся в вашем репозитории, и конкретная фиксация, которую отслеживает отслеживаемый репозиторий. вы можете сказать обновление с помощью
git submodule update --recursive sensitive-files
Чтобы упростить вещи, вы можете зафиксировать символические ссылки в нужном месте, указывая на путь подмодуля.
ln -sf sensitive-files/shadow passwd
Затем добавьте символическую ссылку, как и любой другой файл.
Помните, что подмодуль - это всего лишь извлеченный репозиторий git, вы можете легко ограничить доступ к этому фактическому репозиторию и сделать основной публичный.
Обновлено:
Извините, я пропустил уведомление, если вы все еще работаете над этим.
В вашем личном репозитории вы можете иметь несколько символических ссылок, ссылающихся на закрытый репозиторий (подмодуль), который выгружается в подкаталоге. Каждая из баз данных или того, что используется экземпляром Rails, может быть символической ссылкой в этот закрытый подкаталог.
Кроме того, вам не нужно удаленное указание на частный репозиторий, просто запись в файле .gitmodules, которая автоматически поддерживается подмодулем git. Вам все равно нужно будет защищать частный репозиторий, чтобы доступ к нему мог получить только ваш экземпляр Heroku. Для этого я бы предложил установить gitosis на сервере, если вы можете или использовать какое-то другое частное решение для хостинга git. Добавьте открытый ключ ssh, соответствующий вашему закрытому ключу экземпляра, в список разрешенных пользователей. (Я не знаком с тем, как это сделать в Героку.)
Когда вы нажимаете свои изменения на герою, он должен рекурсивно загружать все подмодули, упомянутые в репозитории.
Ответ 2
Вы можете создать pre-commit hook в своем локальном репо, здесь вы можете написать script, чтобы проверить текущую отмеченную ветку и удалить нарушающий файлы, если они присутствуют до обработки фиксации. Это позволяет избежать файлов, которые когда-либо записывались в истории Git неправильной ветки.
#!/bin/bash
current_branch="$(git branch | sed -e 's/^*//')"
if [ $current_branch != "heroku" ]; then
// Delete sensitive files before commit
rm -f dir1/dir2/exclude_from_public
rm -f dir1/dir2/exclude_from_public_also
fi
exit 0
В качестве альтернативы script может просто проверить файлы и вернуть код выхода "1", уведомив вас о том, что коммит не может действовать, поскольку он содержит конфиденциальные файлы.
Предостережение заключается в том, что вам нужно будет передать этот script всем, кто работает с "привилегированной" веткой heroku, и всегда включать его в свое собственное местное репо.
В идеале вы также должны сделать эту проверку на стороне сервера; но, к сожалению, GitHub предлагает только веб-вариант post-receive hook, поэтому, если вы не являетесь владельцем своего репо, этот подход может выполняться только локально.
Ответ 3
Один из способов сделать это - разместить ваш частный файл в подмодуле и обратиться к этому модулю из вашего публичного репо. (Альтернативно, вы можете поместить свои общедоступные файлы в подмодуль и ссылаться на это репо из своего частного репо.)
Ответ 4
Вот еще несколько вопросов и ответов StackOverflow по строке "как вы выполняете слияние при игнорировании некоторых файлов":
Простейшим, о чем я могу думать, является использование слияния alias
'ed, которое удалит личные файлы перед выполнением слияния. Это будет работать, если вы захотите жить с непереходными слияниями. Здесь alias
:
git config alias.merge-master-exclude-private '!git merge --no-commit --no-ff master && (git diff --name-only HEAD..master | grep -f private_files | while read f; do git reset HEAD -- "$f"; rm -f "$f"; done; git commit -m "Merge master, excluding private files.")'
Затем отредактируйте файл private_files
и добавьте приватные шаблоны файлов; например secret_file.*$
. Вы можете заменить private_files
на псевдоним "$(git rev-parse --show-toplevel)"/private_files
на чтение private_files
из каталога верхнего уровня.
Используйте git merge-master-exclude-private
для слияния. Это приведет к немедленному слиянию без фиксации, поискам файлов, соответствующих шаблонам в файле private_files
, reset
индексу любых личных файлов, удалению личных файлов в рабочем каталоге, а затем фиксации. Это должно обрабатывать файлы с пробелами в именах.
Если вы не хотите совершать коммит, давая вам возможность редактировать сообщение фиксации, удалите -m "Merge master, excluding private files."
из псевдонима.
Ответ 5
Парень по имени Дэвид Альберт написал инструмент под названием Junk, чтобы решить почти эту проблему. Он позволяет передавать файлы из отдельного хранилища нежелательных ящиков вместе с файлами в основном хранилище.
Частные файлы будут иметь отдельные коммиты от публичных, но это может сделать работу.
Ответ 6
Создайте 2 ветки. Единственное ветвь с частными файлами не будет перенаправлена на публичное репо. После слияния восстановите файлы, о которых идет речь, с git checkout HEAD^ -- files that should not have been merged
, rm other files
, git add -A
и git commit --amend -C HEAD
. Я не уверен, в чем разница в файлах, о которых идет речь, но вы получаете эту идею. Сделайте для этого небольшой script, и вам хорошо идти. Вы даже можете зафиксировать список конфиденциальных файлов, который вы зафиксировали в корне, и script может от него отказаться.
Ответ 7
Я знаю, что это оборачивает вопрос, но я бы просто имел два хранилища git. Затем вы можете просто добавить их навсегда в список игнорирования в публичном репозитории.
У вас может быть второй репозиторий для личных файлов и небольшой script, чтобы скопировать изменения в правильное место в производственной системе при развертывании.
Это уменьшает риск того, что когда вы отправитесь в отпуск, а новый стажер обновит публичное репо, ваша личная информация случайно просочится.; -)
Ответ 8
Похоже, вы могли бы использовать mine
.
В основном, он сообщает git избегать содержимого, следующего за соглашением <file or directory>_mine_
, и сам инструмент предоставляет функции snapshot
, clean
и restore
, а не полноценное управление версиями, но для личный материал, он делает трюк красиво.
Все довольно сжато.