Git排除分支的文件,

ff29svar  于 2022-12-10  发布在  Git
关注(0)|答案(2)|浏览(114)

我想忽略分支中的某些文件,而不必依赖于跟踪的.gitignore文件,该文件将在与其他分支合并时被覆盖。
我一直在关注a Stack Overflow answer沿着the linked blog post,但我的repo似乎无法识别.git/config中指定的excludesfile。Git文档(git-configgitignore)似乎没有说明如何为特定分支指定和寻址excludes文件。
我的.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

我的“specialbranch”中没有.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仍然可以工作。
我感觉.git/config无法识别自定义排除文件的地址:

excludesfile = +/info/exclude_specialbranch

...很可能是因为使用+来描述.git目录的位置。
在Git(更新的)版本中,解决自定义排除文件的正确方法是什么?
我运行的是OSX 10.9.5和Git 2.2.1版。

ryevplcw

ryevplcw1#

Git不支持按分支排除文件

你正在尝试实现Git不支持的东西。blog post是这个恶作剧的原始来源,而the Stack Overflow answer只是模仿。正如在该答案下的评论中所指出的,即使是原始的博客文章也包含了一个讨论,指出解决方案不起作用,它链接到一个newer blog post,提到即使是作者也无法重现这种行为。
为什么它不工作?如果你读man gitignoreman git-config,你会发现只有core.excludesfile引用。没有branch.<name>.excludesfilecore.excludesfile是为了让你排除例如Vim .swp文件或其他临时的东西,你的软件使用。
core.excludesfile
除了.gitignore(per-directory)和.git/info/exclude,Git会在这个文件中查找不需要跟踪的文件模式。“~/“会扩展为$HOME,“~user/“会扩展为指定用户的主目录。默认值为$XDG_CONFIG_HOME/git/ignore。如果$XDG_CONFIG_HOME没有设置或为空,使用$HOME/.config/git/ignore。请参阅gitignore(5)

解决方法

我相信,使用post-checkout钩子可以获得最接近于每个分支的excludes文件,它重写了工作树中.gitignore的内容。*
每个分支都有一个.gitignores目录,其中的文件以相应的分支命名。然后,默认情况下会使用一个.gitignores/__default文件。.gitignore会被所有的排除文件排除,并由post-checkout钩子创建为.gitignores中相应文件的副本。
如果你不想跟踪排除文件,你可以做同样的.git/info/exclude文件作为.git/info/excludes/__default等的副本。

  • :* 附注:我曾经建议将.gitignore设置为一个由钩子更新的符号链接,以指向正确的内容,但是.gitignore cannot be symlink since Git v2.32.0。现在,当编辑.gitignore时,在切换分支时更改会丢失,而不是对分支的自定义排除文件进行更改。*
j1dl9f46

j1dl9f462#

下面是我为此编写的脚本:

#!/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: @http://stackoverflow.com/questions/29579546/git-excludesfile-for-a-branch

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

相关问题