git 可以忽略特定行吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6557467/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can git ignore a specific line?
提问by Iolo
I'm using git to sync to phonegap while testing on the phone's native browser. As such I have the following line:
在手机的本机浏览器上进行测试时,我正在使用 git 同步到 phonegap。因此,我有以下几行:
var isPhoneGap = false;
Obviously I change this when building, but is there any way I can set up git to ignore this one line or do I have to go and put it in its own file and ignore it that way?
显然我在构建时改变了这一点,但是有什么方法可以设置 git 来忽略这一行,还是我必须去把它放在自己的文件中并以这种方式忽略它?
I'm using Gitx and the terminal on OSX 10.6.
我在 OSX 10.6 上使用 Gitx 和终端。
回答by VonC
If your file is of a specific type, you can declare a content filter driver, that you can declare in a .gitattributes
file (as presented in the "Keyword expansion" of "Git Attributes"):
如果您的文件是特定类型,您可以声明一个内容过滤器驱动程序,您可以在.gitattributes
文件中声明(如“ Git 属性”的“关键字扩展”中所示):
*.yourType filter=yourFilterName
(you can even set that filter for a specific file, if you want)
(如果需要,您甚至可以为特定文件设置该过滤器)
Implement:
实施:
yourFilterName.smudge
(triggered ongit checkout
) andgit config --global filter.yourFilterName.smudge 'sed "s/isPhoneGap = .*/isPhoneGap = true/"'
yourFilterName.clean
(triggered ongit add
)git config --global filter.yourFilterName.clean 'sed "s/isPhoneGap = .*/isPhoneGap = false/"'
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/"'
Your file would appear unchanged on git status
, yet its checked out version would have the right value for isPhoneGap
.
您的文件在 上看起来没有变化git status
,但其签出版本将具有正确的 值isPhoneGap
。
回答by Carlos
You can use
您可以使用
git update-index --assume-unchanged [file]
to ignore the changes of one file that you don't want track. I use this solution when I need to have a file in the repository but this file have some parts that change that I don't need track always.
忽略您不想跟踪的一个文件的更改。当我需要在存储库中有一个文件时,我会使用此解决方案,但该文件的某些部分会发生变化,而我并不总是需要跟踪这些部分。
When the file have changes that are important you have to do this:
当文件有重要更改时,您必须执行以下操作:
git update-index --no-assume-unchanged [file]
Also, see the Git doc update-indexfor --[no-]assume-unchanged
parameter.
此外,看到的Git文档更新索引的--[no-]assume-unchanged
参数。
When these flags are specified, the object names recorded for the paths are not updated. Instead, these options set and unset the "assume unchanged" bit for the paths. When the "assume unchanged" bit is on, git stops checking the working tree files for possible modifications, so you need to manually unset the bit to tell git when you change the working tree file.
指定这些标志时,不会更新为路径记录的对象名称。相反,这些选项设置和取消设置路径的“假设不变”位。当“假设未更改”位打开时,git 停止检查工作树文件以进行可能的修改,因此您需要手动取消设置该位以告诉 git 何时更改工作树文件。
回答by Andy Ray
Gitx should let you commit or ignore individual lines (you may know that already), but you'd have to do that every time you commit. I think it would be better to have a config file per deployment target (you can version those), and some runtime parameter for however you are starting the server (like ./myserver --config=whatever.js
).
Gitx 应该让您提交或忽略单个行(您可能已经知道了),但是每次提交时都必须这样做。我认为最好为每个部署目标设置一个配置文件(您可以对其进行版本控制),以及一些运行时参数,用于启动服务器(例如./myserver --config=whatever.js
)。
回答by Doron Behar
Continuing https://stackoverflow.com/a/20574486/4935114, @Mikeproposed to create a pre-commit
hook which will grep
in the staged files for the lines which one might want to ignore. The hook checks if those lines were staged. If so, it echo
s a warning and it exit
's with code 1
so the commit process won't continue.
继续https://stackoverflow.com/a/20574486/4935114,@Mike建议创建一个pre-commit
钩子,它将grep
在暂存文件中用于人们可能想要忽略的行。挂钩检查这些行是否已上演。如果是这样,它echo
是一个警告并且它exit
带有代码,1
因此提交过程将不会继续。
Inspired by @Mike's answer, I found myself using perhaps an improved version of his hook which automaticallyreset
s (with the -p
flag) the specific line which we want to ignore.
受到@Mike's answer 的启发,我发现自己可能使用了他的钩子的改进版本,它会自动reset
(带有-p
标志)我们想要忽略的特定行。
I'm not sure this hook will work for a situation where you have many files with this line to be ignored, but this pre-commit
hook looks for a changed in this line in a specific file buildVars.java
. The hook script looked like this when I tested it on my machine.
我不确定此挂钩是否适用于您有许多文件要忽略此行的情况,但此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
Explanation
解释
What I did was echoing a control sequences which searches for the regex isPhoneGap
during an interactive reset
process. Thus emulating a user who presses /
to search for isPhoneGap
, presses y
when asked if he wants to discard this patch and finally presses q
to exit the interactive reset
.
我所做的是回显一个控制序列,该序列isPhoneGap
在交互reset
过程中搜索正则表达式。从而模拟用户按下/
搜索isPhoneGap
,y
在询问他是否要放弃此补丁时按下,最后按下q
退出交互reset
。
The interactive reversed patch process is documented here: https://git-scm.com/docs/git-add#git-add-patch
交互式反向补丁过程记录在此处:https: //git-scm.com/docs/git-add#git-add-patch
NOTE:The above script assuming that the variable interactive.singleKey
is false
. If you configured yours to true
, remove any $'\n'
from the echo
command right after the warning.
注意:上面的脚本假设变量interactive.singleKey
是false
. 如果您将您的配置为true
,请在警告后立即$'\n'
从echo
命令中删除任何内容。
回答by Kache
This is how you can kind of do it with git filters:
这就是你可以用git 过滤器来做的方式:
- Create/Open gitattributes file:
- <project root>/.gitattributes (will be committed into repo)
OR - <project root>/.git/info/attributes (won't be committed into repo)
- <project root>/.gitattributes (will be committed into repo)
- Add a line defining the files to be filtered:
*.rb filter=gitignore
, i.e. run filter namedgitignore
on all*.rb
files
- Define the
gitignore
filter in yourgitconfig
:$ git config --global filter.gitignore.clean "sed '/#gitignore$/'d"
, i.e. delete these lines$ git config --global filter.gitignore.smudge cat
, i.e. do nothing when pulling file from repo
- 创建/打开 gitattributes 文件:
- <project root>/.gitattributes(将提交到repo)
或 - <project root>/.git/info/attributes(不会提交到repo)
- <project root>/.gitattributes(将提交到repo)
- 添加一行定义要过滤的文件:
*.rb filter=gitignore
, 即运行过滤器命名gitignore
的所有*.rb
文件
gitignore
在您的 中定义过滤器gitconfig
:$ git config --global filter.gitignore.clean "sed '/#gitignore$/'d"
, 即删除这些行$ git config --global filter.gitignore.smudge cat
, 即从 repo 中提取文件时什么都不做
Notes:
Of course, this is for ruby files, applied when a line ends with #gitignore
, applied globally in ~/.gitconfig
. Modify this however you need for your purposes.
注意:
当然,这是针对 ruby 文件的,当一行以 结尾时#gitignore
应用,在~/.gitconfig
. 根据您的目的修改它。
Warning!!
This leaves your working file different from the repo (of course). Any checking out or rebasing will mean these lines will be lost! This trick may seem useless since these lines are repeatedly lost on check out, rebase, or pull, but I've a specific use case in order to make use of it.
警告!!
这使您的工作文件与存储库不同(当然)。任何检出或变基都将意味着这些行将丢失!这个技巧似乎没用,因为这些行在检出、变基或拉动时反复丢失,但我有一个特定的用例来利用它。
Just git stash save "proj1-debug"
while the filter is inactive(just temporarily disable it in gitconfig
or something). This way, my debug code can always be git stash apply
'd to my code at any time without fear of these lines ever being accidentally committed.
就git stash save "proj1-debug"
在过滤器处于非活动状态时(只是暂时禁用它gitconfig
或其他东西)。这样,我的调试代码可以随时添加git stash apply
到我的代码中,而不必担心这些行会被意外提交。
I have a possible idea for dealing with these problems, but I'll try implementing it some other time.
我对处理这些问题有一个可能的想法,但我会尝试在其他时间实施它。
Thanks to Rudi and jw013 for mentioning git filters and gitattributes.
感谢 Rudi 和 jw013 提到 git 过滤器和 gitattributes。
回答by patricktokeeffe
A content filter driver is not a good solution. You may be able to hide this line from git status
/etc but it's not really being ignored. As soon as you change the value, your working directory will be marked dirty even though the change may not be visible.
内容过滤器驱动程序不是一个好的解决方案。您也许可以从git status
/etc 中隐藏此行,但它并没有真正被忽略。一旦更改该值,即使更改可能不可见,您的工作目录也将被标记为脏。
If you really want this line out of version control, changing it to a command line argument or placing it in an ignored include or build file may be the only practical means.
如果您真的希望此行脱离版本控制,将其更改为命令行参数或将其放置在忽略的包含或构建文件中可能是唯一实用的方法。
回答by johnb003
I'm guessing this might be something that comes up in more than one line of your source.
我猜这可能是您的源代码中不止一行出现的问题。
I think it would be cleanest to have a .userbuildconfig file of some sort that you just include and have the defaults checked in. Then you can use Carlos's suggestionto mark that file alone as assume unchanged. This way other changes to the file where you need to check the setting are not missed.
我认为拥有某种类型的 .userbuildconfig 文件将是最干净的,您只需包含并签入默认值。然后您可以使用Carlos 的建议将该文件单独标记为假定未更改。这样就不会遗漏需要检查设置的文件的其他更改。
This can allow you to tune preprocessor macros locally (Or for java something like this https://stackoverflow.com/a/1813873/1270965).
这可以让您在本地调整预处理器宏(或者对于 java 类似https://stackoverflow.com/a/1813873/1270965 的东西)。
回答by ralphtheninja
Nope. You can only ignore individual files (and more) since the lines in .gitignore matches file names and not file content. You have already mentioned the solution to this, i.e. ignore a single file that contains that content you want to ignore.
不。您只能忽略单个文件(以及更多),因为 .gitignore 中的行匹配文件名而不是文件内容。您已经提到了解决方案,即忽略包含您要忽略的内容的单个文件。