Git 排除分支文件
Git excludesfile for a branch
我想忽略分支中的某些文件,而不必依赖跟踪的 .gitignore
文件,该文件将在与其他分支合并时被覆盖。
我密切关注 a Stack Overflow answer along with the linked blog post, but my repo doesn’t seem to be recognizing the specified excludesfile
in my .git/config
. The Git documentation (git-config
, gitignore
) 似乎没有说明如何指定和处理特定分支的排除文件。
我的 .git/config
看起来像这样:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
excludesfile = +/info/exclude
[branch "myspecialbranch"]
excludesfile = +/info/exclude_specialbranch
我的 .git/info/exclude
文件看起来像这样(默认情况下,我没有碰它):
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
.DS_Store
我的“特殊分支”中没有 .gitignore
文件。
如果我尝试忽略像 info.php
这样的文件,我的 .git/info/exclude_specialbranch
文件看起来像这样:
info.php
... 但它不会忽略该文件。
如果我 运行 git status --ignored
,它只列出默认 exclude
文件中的 .DS_Store
文件。
但是,如果我将 info.php
添加到我的 .git/info/exclude
文件中:
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
.DS_Store
info.php
它完全忽略了该文件。
请注意,在 .git/config
中 [core]
下没有 excludesfile = +/info/exclude
行它仍然有效。 Git 似乎不需要我告诉它就知道系统范围的 exclude
在哪里。
我感觉 .git/config
无法识别我的自定义排除文件的地址:
excludesfile = +/info/exclude_specialbranch
…很可能是因为使用 +
来描述 .git
目录的位置。
在 Git(更新的)版本中处理自定义排除文件的正确方法是什么?
我正在 运行宁 OSX 10.9.5 和 Git 版本 2.2.1。
Git 不支持每个分支排除文件
您正在尝试实现 Git 不支持的目标。 blog post is the original source of this hoax that the Stack Overflow answer only parroted. As noted in comments under that answer, even the original blog post contains discussion that brings out that the solution does not work and it links to a newer blog post 提到即使是作者也无法重现该行为。
为什么不起作用?如果您阅读 man gitignore
and man git-config
,您会发现仅引用了 core.excludesfile
。那里没有 branch.<name>.excludesfile
。 core.excludesfile
旨在使您能够排除例如Vim .swp 文件或您的软件使用的其他临时文件。
core.excludesfile
In addition to .gitignore
(per-directory) and .git/info/exclude
, Git looks into this file for patterns of files which are not meant to be tracked. "~/
" is expanded to the value of $HOME
and "~user/
" to the specified user’s home directory. Its default value is $XDG_CONFIG_HOME/git/ignore
. If $XDG_CONFIG_HOME
is either not set or empty, $HOME/.config/git/ignore
is used instead. See gitignore(5).
解决方法
我相信每个分支排除文件的最佳近似是使用 post-checkout hook 和通过符号链接实现 .gitignore
来实现的。
每个分支都会有例如一个 .gitignores
目录,其中包含以相应分支命名的文件。然后会有一个默认使用的 .gitignores/__default
文件。 .gitignore
将被所有排除文件排除,并由 post-checkout 挂钩创建为指向 .gitignores
.
中相应文件的符号链接
如果您不想跟踪排除的文件,您可以对 .git/info/exclude
文件执行相同的操作,作为指向 .git/info/excludes/__default
等的符号链接。
这是我为此编写的脚本:
#!/bin/bash
# This is designed to allow per-branch un-ignoring of certain files.
# Use case: Compiled CSS files on master to push to server.
# A special .gitignore file will be present on master at
# {$gitignorePath}/{$disabledMasterGitignoreName} and that file should
# enable the css files using the ! flag. @https://git-scm.com/docs/gitignore
# When the branch specified by script parameters
# is checked out, {$gitignorePath}/{$disabledMasterGitignoreName} is
# copied to .gitignore.
# On other branches this gitignore file is named $disabledMasterGitignoreName, versioned,
# and {$gitignorePath}.gitignore will be deleted. Note, you must ignore
# {$gitignorePath}.gitignore from your main .gitignore file
#
# To enable put this file in your path and call this script
# in .git/hooks/post-checkout with pass a list of single-space-separated branches that
# will enable the branch-specific .gitignore.
# One caveat is that you can only merge into the branch containing the .gitignore
# file. Otherwise you'll end up re-committing the files. This is fine if you are
# using gitflow and `master` contains your special .gitigore using the ! syntax
# that is un-ignoring files.
#
# Background: @
set -e
gitignorePath='docroot/sites/all/themes'
disabledMasterGitignoreName='.gitignore_master--disabled'
#branchWithGitignoreEnabled='master'
branch=$(git rev-parse --abbrev-ref HEAD)
gitignoreRoot="$(git rev-parse --show-toplevel)/${gitignorePath}"
if [ -f "${gitignorePath}/.gitignore" ]
then
masterGitignoreExists=true
fi
if [ -f "${gitignorePath}/${disabledMasterGitignoreName}" ]
then
disabledMasterGitignoreExists=true
fi
IFS=' ' read -a params <<< "$@"
if [[ " ${params[@]} " =~ " ${branch} " ]]
then
if [ $disabledMasterGitignoreExists ]
then
cp -f "${gitignoreRoot}/${disabledMasterGitignoreName}" "${gitignoreRoot}/.gitignore"
echo "Enabled ${gitignorePath}/.gitignore"
fi
elif [ $masterGitignoreExists ]
then
rm -f "${gitignorePath}/.gitignore"
if [ masterGitignoreExists ]
then
echo "Disabled ${gitignorePath}/.gitignore"
fi
fi
我想忽略分支中的某些文件,而不必依赖跟踪的 .gitignore
文件,该文件将在与其他分支合并时被覆盖。
我密切关注 a Stack Overflow answer along with the linked blog post, but my repo doesn’t seem to be recognizing the specified excludesfile
in my .git/config
. The Git documentation (git-config
, gitignore
) 似乎没有说明如何指定和处理特定分支的排除文件。
我的 .git/config
看起来像这样:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
excludesfile = +/info/exclude
[branch "myspecialbranch"]
excludesfile = +/info/exclude_specialbranch
我的 .git/info/exclude
文件看起来像这样(默认情况下,我没有碰它):
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
.DS_Store
我的“特殊分支”中没有 .gitignore
文件。
如果我尝试忽略像 info.php
这样的文件,我的 .git/info/exclude_specialbranch
文件看起来像这样:
info.php
... 但它不会忽略该文件。
如果我 运行 git status --ignored
,它只列出默认 exclude
文件中的 .DS_Store
文件。
但是,如果我将 info.php
添加到我的 .git/info/exclude
文件中:
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
.DS_Store
info.php
它完全忽略了该文件。
请注意,在 .git/config
中 [core]
下没有 excludesfile = +/info/exclude
行它仍然有效。 Git 似乎不需要我告诉它就知道系统范围的 exclude
在哪里。
我感觉 .git/config
无法识别我的自定义排除文件的地址:
excludesfile = +/info/exclude_specialbranch
…很可能是因为使用 +
来描述 .git
目录的位置。
在 Git(更新的)版本中处理自定义排除文件的正确方法是什么?
我正在 运行宁 OSX 10.9.5 和 Git 版本 2.2.1。
Git 不支持每个分支排除文件
您正在尝试实现 Git 不支持的目标。 blog post is the original source of this hoax that the Stack Overflow answer only parroted. As noted in comments under that answer, even the original blog post contains discussion that brings out that the solution does not work and it links to a newer blog post 提到即使是作者也无法重现该行为。
为什么不起作用?如果您阅读 man gitignore
and man git-config
,您会发现仅引用了 core.excludesfile
。那里没有 branch.<name>.excludesfile
。 core.excludesfile
旨在使您能够排除例如Vim .swp 文件或您的软件使用的其他临时文件。
core.excludesfile
In addition to
.gitignore
(per-directory) and.git/info/exclude
, Git looks into this file for patterns of files which are not meant to be tracked. "~/
" is expanded to the value of$HOME
and "~user/
" to the specified user’s home directory. Its default value is$XDG_CONFIG_HOME/git/ignore
. If$XDG_CONFIG_HOME
is either not set or empty,$HOME/.config/git/ignore
is used instead. See gitignore(5).
解决方法
我相信每个分支排除文件的最佳近似是使用 post-checkout hook 和通过符号链接实现 .gitignore
来实现的。
每个分支都会有例如一个 .gitignores
目录,其中包含以相应分支命名的文件。然后会有一个默认使用的 .gitignores/__default
文件。 .gitignore
将被所有排除文件排除,并由 post-checkout 挂钩创建为指向 .gitignores
.
如果您不想跟踪排除的文件,您可以对 .git/info/exclude
文件执行相同的操作,作为指向 .git/info/excludes/__default
等的符号链接。
这是我为此编写的脚本:
#!/bin/bash
# This is designed to allow per-branch un-ignoring of certain files.
# Use case: Compiled CSS files on master to push to server.
# A special .gitignore file will be present on master at
# {$gitignorePath}/{$disabledMasterGitignoreName} and that file should
# enable the css files using the ! flag. @https://git-scm.com/docs/gitignore
# When the branch specified by script parameters
# is checked out, {$gitignorePath}/{$disabledMasterGitignoreName} is
# copied to .gitignore.
# On other branches this gitignore file is named $disabledMasterGitignoreName, versioned,
# and {$gitignorePath}.gitignore will be deleted. Note, you must ignore
# {$gitignorePath}.gitignore from your main .gitignore file
#
# To enable put this file in your path and call this script
# in .git/hooks/post-checkout with pass a list of single-space-separated branches that
# will enable the branch-specific .gitignore.
# One caveat is that you can only merge into the branch containing the .gitignore
# file. Otherwise you'll end up re-committing the files. This is fine if you are
# using gitflow and `master` contains your special .gitigore using the ! syntax
# that is un-ignoring files.
#
# Background: @
set -e
gitignorePath='docroot/sites/all/themes'
disabledMasterGitignoreName='.gitignore_master--disabled'
#branchWithGitignoreEnabled='master'
branch=$(git rev-parse --abbrev-ref HEAD)
gitignoreRoot="$(git rev-parse --show-toplevel)/${gitignorePath}"
if [ -f "${gitignorePath}/.gitignore" ]
then
masterGitignoreExists=true
fi
if [ -f "${gitignorePath}/${disabledMasterGitignoreName}" ]
then
disabledMasterGitignoreExists=true
fi
IFS=' ' read -a params <<< "$@"
if [[ " ${params[@]} " =~ " ${branch} " ]]
then
if [ $disabledMasterGitignoreExists ]
then
cp -f "${gitignoreRoot}/${disabledMasterGitignoreName}" "${gitignoreRoot}/.gitignore"
echo "Enabled ${gitignorePath}/.gitignore"
fi
elif [ $masterGitignoreExists ]
then
rm -f "${gitignorePath}/.gitignore"
if [ masterGitignoreExists ]
then
echo "Disabled ${gitignorePath}/.gitignore"
fi
fi