Умеет ли git/hg/other игнорировать локальные изменения?

bleyman

Есть например скриптик или конфигурационный файл в который можно вписать sensitive information или просто что-то что имеет смысл только локально, типа логин/пароль/путь куда-нибудь. Хочется чтобы в remote repository хранилась как бы темплейтная версия без этой информации, она попадала во все клоны/чекауты, но дальше там как минимум игнорировалась, то есть после того как что-нибудь изменил в репозитории и пушнул изменения обратно, в эти изменения ни в коем случае случайно не включились изменения в этом файлике. То есть например git status их показывать не должен, `git add .` или `git commit -a` не должны добавлять, и так далее.
В гите вроде есть какие-то стрёмные штуки вроде `update-index --assume-unchanged`, `update-index --skip-worktree`, и опция sparse-checkout, но они все какие-то дико стрёмные, ибо предназначены для оптимизации и могут внезапно отключиться (после git reset например).
Может, есть что-то ещё более хитро запрятанное? Алсо, есть ли что-нибудь подобное в Меркуриале, или в других vcs?
Алсо, может, можно как-то это сделать на уровне бранчей? Типа, мои изменения тоже лежат под контролем в бранче local-master который никогда ни за что не заливается на ремоут, причём можно как-то настроить безболезненный мерж моего бранча в мастер игнорируя этот файл, естественно?

okis

У нас есть конфиг файл config.*.default, который на продакшене копируется в config.*
и изменяется вручную по необходимости.
Вообще есть .gitignore, который может задать маску игнора, чтобы игнорировать изменения в отдельных файлах — такого не знаю (кроме приведённого тобой способа).

Alena_08_11

hgignore

procenkotanya

Пацаны, ваши .gitignore и .hgignore не решают проблему автора: если файл уже трекится, его добавление в .*ignore не влияет: он будет попадать в diff и commit [-a].

bleyman

Ага, впрочем имеет в виду что в репозитории лежит config.zzz.default и гитигнор, в который записан config.zzz, который в репозитории как раз таки не лежит. Ну да, такая стройная система костылей и подпорок доставляет как минимум базовую функциональность.

okis

Как вариант, можно считать, что правки на продакшене (кроме конфигов) не делаются никогда (или делаются, но очень аккуратно). Тогда может помочь git stash && git pull && git stash apply. А этот stash можно как-нибудь в patch собрать (для распространения на другие сервера, например). Но это, опять же, внерепозиторный механизм.

shlyumper

Если привычки использовать `git commit -a` не глядя нет (а от нее все равно лучше избавляться то:

git stash --keep-index
# опционально, если файл "с паролями" правился:
git stash --keep-index --patch
git commit
git stash pop

bansek

я использую иде для этого - такие "некомитящиеся" файлы храню в отдельном changelist, а не в дефолтном, так что идея их не трогает при комите

Bayur19

я использую иде для этого - такие "некомитящиеся" файлы храню в отдельном changelist, а не в дефолтном, так что идея их не трогает при комите
Причем не обязательно IDE использовать, можно из командной строки сделать "Ignored" changelist

bleyman

Хм, расскажи поподробнее, наивное гугление не помогло!

Bayur19

Хм, расскажи поподробнее, наивное гугление не помогло!
ну тупо делаю changelist с названием Ignored и никогда не коммичу его содержимое =)
Летом стал использовать, привычка уже выработалась стойкая )

erotic

Алсо, может, можно как-то это сделать на уровне бранчей? Типа, мои изменения тоже лежат под контролем в бранче local-master который никогда ни за что не заливается на ремоут, причём можно как-то настроить безболезненный мерж моего бранча в мастер игнорируя этот файл, естественно?
Пробовал такую схему (тестово, реально не стал использовать):
Исходники конфигов лежат в мастере, причем в конфигах есть общая часть и заготовка частной, локализованы в разных кусках файла для уменьшения конфликтов при мердже. Для каждой машины ветка, в нее вносятся частные изменения. Общие изменения должны так или иначе попадать в мастер: либо сразу туда их коммитить, либо если что-то общее изменено в машинной ветке (отдельным коммитом без изменений локальных данных то этот коммит черри-пикается в мастер. В остальные машинные ветки мастер мерджится, сливая новые общие записи со старыми, что получается довольно неплохо при условии их изолированности от частных данных.

bleyman

Ну объясните же мне как тупому, детально, как вы ( & Vozbu) это делаете, показывая конкретные команды! И сразу скажите, в результате вам удаётся-то сделать `git push` без дополнительных параметров и чтобы ненужные чейнджсеты автоматически не аплоадились?

Bayur19

Ну объясните же мне как тупому, детально, как вы ( & Vozbu) это делаете, показывая конкретные команды! И сразу скажите, в результате вам удаётся-то сделать `git push` без дополнительных параметров и чтобы ненужные чейнджсеты автоматически не аплоадились?
Это достигается тем, что коммичу только ченджлистами.
Как клиенту запретить автоматически не коммитить определенный чейнджлист - не знаю.
Скриншоты с работы на примере svn (git/hg/ other):
IDEA

Tortouse SVN

Иногда возникает необходимость коммитить из командной строки.
Первый попавшийся нагугленный пример
http://alexander-simakov.blogspot.com/2010/07/changelists-su...

erotic

Пример с веткой мастер с шаблонами конфигов и machineA - реальными конфигами. Также иллюстрирует достоинства и недостатки данного метода. Аналогично можно добавить другие ветки для конкретных машин.
Еще пробежался глазами по секции filter в man gitattributes. Может быть с этим что-то можно сделать, хотя я даже не пытался про это думать.

swift ~ $ cd programming/
swift ~/programming $ mkdir cfg
swift ~/programming $ cd cfg/
swift ~/programming/cfg $ git init
Initialized empty Git repository in /home//programming/cfg/.git/
swift ~/programming/cfg $ cat >> config << EOF
> common config part
> another common config part
>
> # private part
> # empty in master
> user
> port
> EOF
swift ~/programming/cfg $ git add config
swift ~/programming/cfg $ git commit -m "cfg template in master"
[master (root-commit) 102a264] cfg template in master
1 files changed, 7 insertions(+ 0 deletions(-)
create mode 100644 config
swift ~/programming/cfg $ git checkout -b machineA
Switched to a new branch 'machineA'
swift ~/programming/cfg $ sed 's/port/port 10/' -i config
swift ~/programming/cfg $ sed 's/user/user /' -i config
swift ~/programming/cfg $ git diff | cat
diff --git a/config b/config
index 79dcc0d..06e0681 100644
--- a/config
+++ b/config
@@ -3,5 +3,5 @@ another common config part

# private part
# empty in master
-user
-port
+user
+port 10
swift ~/programming/cfg $ git commit -a -m "machinaA parameters"
[machineA 4588414] machinaA parameters
1 files changed, 2 insertions(+ 2 deletions(-)
swift ~/programming/cfg $ git checkout master
Switched to branch 'master'
swift ~/programming/cfg $ sed 's/common config part/master config part/' -i config
swift ~/programming/cfg $ sed -e 's/\(another.*part\)/\1\nonce more common option/' -i config
swift ~/programming/cfg $ git diff | cat
diff --git a/config b/config
index 79dcc0d..3852ab9 100644
--- a/config
+++ b/config
@@ -1,5 +1,6 @@
-common config part
-another common config part
+master config part
+another master config part
+once more common option

# private part
# empty in master
swift ~/programming/cfg $ git commit -a -m "common parameters changed"
[master 5e2f643] common parameters changed
1 files changed, 3 insertions(+ 2 deletions(-)
swift ~/programming/cfg $ git checkout machineA
Switched to branch 'machineA'
swift ~/programming/cfg $ cat config
common config part
another common config part

# private part
# empty in master
user
port 10
swift ~/programming/cfg $ git merge master
Auto-merging config
Merge made by recursive.
config | 5 +++--
1 files changed, 3 insertions(+ 2 deletions(-)
swift ~/programming/cfg $ cat config
master config part
another master config part
once more common option

# private part
# empty in master
user
port 10
swift ~/programming/cfg $ sed 's/user /user vvvooozzzbbboooooo/' -i config
swift ~/programming/cfg $ git diff | cat
diff --git a/config b/config
index 3356769..654faaa 100644
--- a/config
+++ b/config
@@ -4,5 +4,5 @@ once more common option

# private part
# empty in master
-user
+user vvvooozzzbbboooooo
port 10
swift ~/programming/cfg $ git commit -a -m "user"
[machineA 5b34557] user
1 files changed, 1 insertions(+ 1 deletions(-)
swift ~/programming/cfg $ sed -e 's/\(once.*\)/\1\ncommon option from machineA/' -i config
swift ~/programming/cfg $ git diff | cat
diff --git a/config b/config
index 654faaa..c072828 100644
--- a/config
+++ b/config
@@ -1,6 +1,7 @@
master config part
another master config part
once more common option
+common option from machineA

# private part
# empty in master
swift ~/programming/cfg $ git commit -a -m "common option from machineA"
[machineA 8b5e5bc] common option from machineA
1 files changed, 1 insertions(+ 0 deletions(-)
swift ~/programming/cfg $ git checkout master
Switched to branch 'master'
swift ~/programming/cfg $ git cherry-pick machineA
[master 9e6fcb8] common option from machineA
1 files changed, 1 insertions(+ 0 deletions(-)
swift ~/programming/cfg $ cat config
master config part
another master config part
once more common option
common option from machineA

# private part
# empty in master
user
port
swift ~/programming/cfg $ sed -e 's/\(user.*\)/\1\npass/' -i config
swift ~/programming/cfg $ git diff | cat
diff --git a/config b/config
index bd57ade..df75e18 100644
--- a/config
+++ b/config
@@ -6,4 +6,5 @@ common option from machineA
# private part
# empty in master
user
+pass
port
swift ~/programming/cfg $ git commit -a -m "try to add option to private part. possible merge conflicts"
[master 0ceb37a] try to add option to private part. possible merge conflicts
1 files changed, 1 insertions(+ 0 deletions(-)
swift ~/programming/cfg $ git checkout machineA
Switched to branch 'machineA'
swift ~/programming/cfg $ git merge master
Auto-merging config
CONFLICT (content): Merge conflict in config
Automatic merge failed; fix conflicts and then commit the result.
swift ~/programming/cfg $ cat config
master config part
another master config part
once more common option
common option from machineA

# private part
# empty in master
<<<<<<< HEAD
user vvvooozzzbbboooooo
port 10
=======
user
pass
port
>>>>>>> master


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

bleyman

Ну, эта часть как раз понятна и неинтересна.
Теперь представь что машина А — это моя девелоперская машина. И я в ней что-то пишу и коммичу. Как мне наиболее безболезненно после написания очередной фичи смержить только эту фичу в мастер, или в отдельный бранч и потом может быть в мастер, чтобы туда не попало содержимое файла config из бранча machineA?
То есть это как бы не просто нормальный, а даже и частый use case. Я даже себе специальный питономодуль написал для него, который достаёт конфигурационные переменные из sqlite базочки в ~/.simple_config (или спрашивает их значения, если их там ещё нет настолько часто мне приходится такое делать.
Я не хочу тратить часы, дни, годы своей жизни на черрипикинг перед `git push`. Я не хочу стрематься что я забыл это сделать когда я делаю `git push` после восьми часов кодинга.

mat

https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes#_merge_strategies

Merge Strategies (в самом низу)
Оставить комментарий
Имя или ник:
Комментарий: