Reputation: 103
Aka. Best practice to have version control on files that are in my ignore config (e.g. gitignore).
Hi, this question may seems weird first but let me explain: We have quite some ignored config files in our projects. They get brought to the developer by checked in .dist
versions of the config, as this is a well known workflow. (Configs contain dev specific, sometimes sensitive, information that should not be committed.)
Now what I would like to have are the local advantages of version control on those files, too. I want to see what I changed. I want to be able to revert back or stash changes. All without pushing to any remote of corse.
Specific working examples:
All I came up with was mixing in a different version control system. Or temporarily adding the files to my git and redoing that again, once I am done. Both feel wrong.
Did you ever though about that or use something to prevent mentioned problems?
UPDATE:
Thanks for existing answers! I would like to not have to have separate folders and I would like to have the version control system recognize "new" (but ignored) files by itself.
Upvotes: 1
Views: 149
Reputation: 51780
You can tell git to use an alternate .git/
folder using the GIT_DIR
environment variable or git --git-dir <dir>
cli parameter.
You can use this to track your config files in a separate directory.
A note about the caveats : tracking files in an unrelated repo makes your config files not follow automatically the version of the code, e.g : after running git checkout v1.0
, you would need to separately update your configuation.
You may also have clashes between your main repo and the auxiliary config repo in case the directory structure change.
choose a place to store your config files : either a repo which will be global to your machine (~/.projectcfg
) or next to your repo (../projectcfg
)
add an alias in your repo's config, to target this gitdir, and also keep the same worktree as your main project :
# replace <cfgdir> with either '~/.projectcfg' or '$rootdir/../projectcfg'
git config alias.projectcfg '! _f () { local rootdir=$(git rev-parse --show-toplevel); git --git-dir <cfgdir> --work-tree "$rootdir" "$@"; }; _f'
git projectcfg init
once, to initialize this repoinfo/exclude
file in that repo, to only keep config files :# vi <cfgdir>/info/exclude :
# ignore all files :
*
# keep the config files you want to target :
!*.ini
!*.conf
git projectcfg <command>
:git projectcfg checkout -b myproject
git projectcfg add -f path/to/config.ini
git projectcfg commit
git projectcfg log
...
You probably named your config files in .gitignore
files stored in the repository.
If this is the case, the files will not appear as untracked if you git projectcfg status
, and you will need to use the add -f
option to add these files.
One way to change this behavior can be :
.git/info/exclude
file of your main project,.gitignore
filesThe main impact here is : since the info/exclude
file is not versioned with the repository, other users won't get it automatically.
What you can do is : commit a script, which sets up the above elements.
Upvotes: 0
Reputation: 30858
My solution is to use annotated tag
. A tag can point to a git object, and an annotated one has a message like a commit does.
1.Create a blob object for a config file, foo.config
, and get its SHA1, even if it's ignored.
sha1=$(git hash-object -w foo.config)
2.Create an annotated tag, config_v0.1
, referring to the blob.
git tag -m"init foo.config" config_v0.1 $sha1
# or combine the 2 commands
git tag -m"init foo.config" config_v0.1 $(git hash-object -w foo.config)
3.Disable these tags from being pushed with the help of the hook pre-push
.
#!/bin/bash
# pre-push sample
while read local_ref local_sha remote_ref remote_sha;do
if [[ "${local_ref}" =~ refs/tags/config ]];then
echo Forbidden tag detected ${local_ref}
exit 1
fi
done
4.List these config tags with messages.
git tag -l config_* -n999
5.Compare the diff between two config files.
git diff config_v0.1 config_v0.2
6.Overwrite foo.config
with the content of config_v0.2
. Be careful. Tag the current foo.config
first if it's not been tagged yet.
git show config_v0.2^{} > foo.config
It would be troublesome if there are lots of config files. You can wrap these commands with git alias or shell functions. And to manage multiple config files under the same folder, tree objects are worth a try. Suppose there are foo.config
and bar.config
.
1.Convert them to blobs.
foosha1=$(git hash-object -w foo.config)
barsha1=$(git hash-object -w bar.config)
2.Write a tree file tree.txt
. Suppose foosha1
is ce013625030ba8dba906f756967f9e9ca394464a
and foosha2
is aa2fc61b2166263d32d25192df25ee218692b05d
. Note that <SP>
stands for a space and <TAB>
for a tab.
10064<SP>blob<SP>ce013625030ba8dba906f756967f9e9ca394464a<TAB>foo.config
10064<SP>blob<SP>aa2fc61b2166263d32d25192df25ee218692b05d<TAB>bar.config
3.Create a tree object from tree.txt
.
treesha1=$(git mktree < tree.txt)
4.Tag the tree.
git tag -m"init config files" config_tree_v0.1 ${treesha1}
# or combine the 2 commands
git tag -m"init config files" config_tree_v0.1 $(git mktree < tree.txt)
5.List the tree.
git ls-tree config_tree_v0.1
6.Overwrite foo.config
with the version in config_tree_v0.1
. Tag the current foo.config
first if it's not tagged yet.
git show config_tree_v0.1:foo.config > foo.config
This is not a convenient solution. I hope it could give you some hints. You could also put these config files in a nested git repository and don't add it as a submodule.
Upvotes: 2