git可以忽略特定的行吗?


114

在手机的本机浏览器上测试时,我正在使用git同步到phonegap。因此,我有以下几行:

var isPhoneGap = false;

显然,我在构建时会更改此设置,但是有什么方法可以设置git来忽略这一行,还是我必须将其放在自己的文件中并以这种方式忽略它?

我正在使用Gitx和OSX 10.6上的终端。


@ user494461:Git过滤器就是这样做的方法:stackoverflow.com/a/16244970/520162
eckes 2014年

1
您是否无法检测到环境并使用环境配置文件?
exussum 2014年

简而言之:不。但是我编写了一个预处理程序脚本,该脚本查找某些注释的代码,并在发布到git之前将其删除。在这里查看:github.com/franklinchou/ahk_config/blob/master/preprocess.sh
franklin

Answers:


103

如果文件属于特定类型,则可以声明一个内容过滤器驱动程序,该.gitattributes文件可以在文件中声明(如“ Git Attributes ” 的“关键字扩展”中所述):

http://git-scm.com/figures/18333fig0702-tn.png

*.yourType filter=yourFilterName

(您甚至可以为特定文件设置该过滤器

实行:

  • yourFilterName.smudge(在上触发git checkout)和

    git config --global filter.yourFilterName.smudge 'sed "s/isPhoneGap = .*/isPhoneGap = true/"'
    
  • yourFilterName.clean(已触发git add

    git config --global filter.yourFilterName.clean 'sed "s/isPhoneGap = .*/isPhoneGap = false/"'
    

您的文件在上将保持不变git status,但其签出的版本将具有正确的值isPhoneGap


1
谢谢你 使它工作。您知道如何设置git diff or git status`,但忽略过滤器吗?所以我仍然可以看到有什么不同?我的用例是调试日志...最终我要删除... @jthill @VonC
timh 2014年

1
@timh如果过滤器正在工作,则git status或git diff不显示任何内容。
VonC 2014年

1
很遗憾,GIT中没有简单的方法。git ignore <文件名> <行号>会非常方便!
kiedysktos

22
@kiedysktos行号?如果行号发生变化怎么办?
VonC

这很好用,但是Windows用户要注意,gitconfig想要保留哪些字符非常挑剔,因此在尝试使用一些半异形正则表达式时,您可能会遇到麻烦。最后,我将sed调用放在了我从gitconfig调用的单独的helper.sh文件中,sh ".git/helper.sh"并确保将所有参数传递给sed "$@"(我假设只是传递了文件路径)。
ohaal

43

您可以使用

git update-index --assume-unchanged [file]

忽略不想跟踪的一个文件的更改。当我需要在存储库中有一个文件,但是此文件中的某些部分发生更改时,我不需要始终跟踪,因此可以使用此解决方案。

当文件具有重要的更改时,您必须执行以下操作:

git update-index --no-assume-unchanged [file]

另外,请参阅Git doc update-index以获取--[no-]assume-unchanged参数。

指定这些标志时,为路径记录的对象名称不会更新。而是,这些选项设置和取消设置路径的“假定不变”位。当“假定未更改”位打开时,git停止检查工作树文件以进行可能的修改,因此您需要手动取消设置该位以在更改工作树文件时告诉git。


2
当我执行git pull时,这样做是否仍会获取新版本?
Saad Rehman Shah

1
@Caffeine当您执行git pull时,会得到提交的最后一个版本,这将是更改为“-假定未更改”文件之前的最后一个版本。
卡洛斯

1
我相信--skip-worktree对于大多数目的而言,这是一个更好的选择。stackoverflow.com/a/39583010/4233593
杰夫·普基特


3
这会忽略对整个文件的更新,而不是对特定行的更新
nikoss

6

Gitx应该让您提交或忽略个别行(您可能已经知道),但是每次提交时都必须这样做。我认为最好为每个部署目标提供一个配置文件(您可以对它们进行版本控制),并为启动服务器(例如./myserver --config=whatever.js)设置一些运行时参数。


5

继续https://stackoverflow.com/a/20574486/4935114@Mike提出创建一个pre-commit钩子,将grep在上演文件其中一个可能要忽略线。挂钩检查是否已暂存这些行。如果是这样,它echo是一个警告,并且exit带有代码,1因此提交过程将不会继续。

受到@Mike的回答的启发,我发现自己使用的是他的钩子的改进版本,该钩子会自动 reset(带有-p标志)自动设置要忽略的特定行。

我不确定此挂钩是否可以在您有很多文件需要忽略此行的情况下使用,但是此pre-commit挂钩会在特定文件的该行中查找更改buildVars.java。当我在机器上测试钩子脚本时,它看起来像这样。

#!/bin/sh

# this hook looks for lines with the text `var isPhoneGap = false;` in the file `buildVars.java` and it resets these lines to the previous state before staged with `reset -p`

if [[ $(git diff --no-ext-diff --cached buildVars.java | grep --count -e "var\ isPhoneGap[\ ]*=[\ ]*") -ne 0 ]]; then
    cat <<EOW
WARNING: You are attempting to commit changes which are not supposed to be commited according to this \`pre-commit\` hook
This \`pre-commit\` hook will reset all the files containing this line to it's previous state in the last commit.
EOW
    echo /$'\n'isPhoneGap$'\n'y$'\n'q | git reset -p
    # BONUS: Check if after reseting, there is no actual changes to be commited and if so, exit 1 so the commit process will abort.
    if [[ $(git diff --no-ext-diff --cached | wc -l) -eq 0 ]]; then
        echo there are no actual changes to be commited and besides the change to the variable \'isPhoneGap\' so I won\'t commit.
        exit 1
    fi
fi

说明

我所做的是回显一个控制序列,该序列isPhoneGap在交互reset过程中搜索正则表达式。因此,模拟了按/一下搜索的用户isPhoneGapy在被问到是否要放弃此补丁时按q一下,最后按一下退出交互reset

交互式反向补丁程序记录在这里:https : //git-scm.com/docs/git-add#git-add-patch


注意:上面的脚本假定变量interactive.singleKeyfalse。如果将设置为true,则在警告后立即$'\n'echo命令中删除任何命令。


3

这是您可以使用git过滤器完成的方式

  1. 创建/打开gitattributes文件:
    • <项目根目录> /。gitattributes(将提交到存储库中)
    • <项目根目录> /。git / info / attributes(不会提交到仓库中)
  2. 添加一行以定义要过滤的文件:
    • *.rb filter=gitignore,即gitignore在所有*.rb文件上运行命名的过滤器
  3. gitignore在您的中定义过滤器gitconfig
    • $ git config --global filter.gitignore.clean "sed '/#gitignore$/'d",即删除这些行
    • $ git config --global filter.gitignore.smudge cat,即从仓库中提取文件时什么也不做

注意:
当然,这是针对ruby文件,当行以结尾时#gitignore应用,在中全局应用~/.gitconfig。修改此,但是您需要为您的目的。

警告!!
这使您的工作文件与存储库不同(当然)。任何签出或重新定基将意味着这些线将丢失!这个技巧似乎没用,因为这些行在检出,重新设置基数或拉回时会反复丢失,但是为了使用它,我有一个特定的用例。

git stash save "proj1-debug" 在过滤器处于非活动状态时(只是暂时将其禁用gitconfig)。这样,我的调试代码始终可以随时添加git stash apply到我的代码中,而不必担心这些行会被意外提交。

对于解决这些问题,我有一个可能的主意,但是我将在其他时间尝试实施。

感谢Rudi和jw013提到git过滤器和gitattributes。


2

内容筛选器驱动程序不是一个好的解决方案。您也许可以从git status/ etc 隐藏该行,但实际上并没有被忽略。更改该值后,即使更改可能不可见,您的工作目录也会被标记为脏目录。

如果您确实希望此行脱离版本控制,则将其更改为命令行参数或将其置于忽略的包含或构建文件中可能是唯一实用的方法。


“一旦更改了该值,即使更改可能不可见,您的工作目录也会被标记为脏目录”:如果干净的脚本仍将文件还原为原始内容,则不会。
VonC 2014年

那就是我的想法。我正在使用GitExtensions,即使diff窗格为空白,它也会显示文件已修改。可能是因为只有在文件签入后才运行干净过滤器。可能是因为它是msysgit,而不是git-git。IDK,YMMV
patricktokeeffe 2014年

1

我猜这可能是源代码中多行出现的问题。

我认为拥有一个仅包含某种类型的.userbuildconfig文件并签入默认值是最干净的。然后,您可以使用Carlos的建议将该文件单独标记为假定为未更改。这样,就不会丢失对需要检查设置的文件的其他更改。

这可以让您在本地调整预处理器宏(或对于Java,例如https://stackoverflow.com/a/1813873/1270965)。


-1

不。您只能忽略单个文件(或更多文件),因为.gitignore中的行与文件名匹配,而不与文件内容匹配。您已经提到了解决方案,即忽略包含要忽略的内容的单个文件。


我同意,就我而言,仅包含来自被忽略文件的内容就足够了并且可能。因此,移动所有可忽略的设置。那里。另外,我还创建了该被忽略文件的副本,并将其添加到索引中作为参考,因此不会丢失有关该文件中内容的信息。
Urs
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.