如何告诉Git忽略单独的代码行,即为特定代码行创建.gitignore文件。

246

.gitignore 可以忽略整个文件,但是否有一种方法在编码时忽略特定行的代码?

我在项目中经常重复添加相同的调试代码行,只需记得在提交之前删除它们。 我想保留这些行的代码,并让 git 忽略它们。


143
我不确定这是个糟糕的主意还是一个妙计。 - Kyle Strand
2
至少,我可以将其添加到我键入的调试行中,并确信它们不会被意外提交。 - Kache
8
好的,那就是“精彩”的部分了。 - Kyle Strand
哦,那你就可以直接更改 sed 的正则表达式。 - Kache
@Miguelos 哈,看起来这是一个重复的问题。虽然这个问题要早得多,但那个问题的获奖答案比我的问题和我的答案都要新。 - Kache
显示剩余3条评论
2个回答

198
这是使用git filters的方法:
  1. 创建/打开 gitattributes 文件:
    • <project root>/.gitattributes (将被提交到仓库)
      OR
    • <project root>/.git/info/attributes (不会被提交到仓库)
  2. 添加一行定义要过滤的文件:
    • *.rb filter=gitignore,即在所有*.rb文件上运行名为gitignore的过滤器
  3. 在你的gitconfig中定义gitignore过滤器:
    • $ git config --global filter.gitignore.clean "sed '/#gitignore$/d'",即删除这些行
    • $ git config --global filter.gitignore.smudge cat,即从仓库拉取文件时不进行任何操作
注意:
当一行以#gitignore结尾时,此方法适用于ruby文件,在~/.gitconfig中全局应用。根据您的需求进行修改。
警告!!
这将使您的工作文件与存储库不同(当然)。任何检出或变基都意味着这些行将丢失!这个技巧似乎毫无用处,因为这些行在检出、变基或拉取时会反复丢失,但我有一个特定的用例来利用它。
只需在过滤器处于非活动状态时执行git stash save "proj1-debug"(暂时在gitconfig或其他地方禁用它)。这样,我的调试代码可以随时git stash apply到我的代码中,而不必担心这些行会被意外提交。
我有一个可能处理这些问题的想法,但我将在其他时间尝试实现它。
感谢Rudi和jw013提到了git filters和gitattributes。

2
应该这样写:git config --global filter.gitignore.clean sed '/#gitignore$/d',因为你已经将过滤器命名为 gitignore - Onur Yıldırım
1
我为 '.py' 文件做了这个,它起作用了。然后我又为 '.xml' 文件做了一次,但是没有起作用,而且还破坏了之前 python 文件的过滤器。现在我一直得到这个错误:“error: external filter sed”。你知道我怎么能修复它或者仅仅删除所有的过滤器吗? - PaulMag
5
这很有趣。但它基本上像问题所在的那一行不存在一样。它不适用于忽略某行中的更改内容。所以,例如,你不能仅仅通过函数调用来改变变量的值。例如,如果要将flags = foo | bar更改为flags = foo | bar | debug_thingy,则必须确保在之后添加一个全新的行,如flags |= debug_thingy - Kat
3
我找到了适合我的解决方案。我正在使用 git config --global filter.gitignore.clean "sed 's/.*gitignore//'" 并替换这样的代码 , var x = replaced #gitignore var x = 42。所以在 #gitignore 后面的内容将替换该行,因此必须保留 #gitignore 后面的缩进。 - Jp_
1
这里还有一个sed命令,用于忽略代码块:"sed '/^# start git-block-ignore/,/^# end git-block-ignore/d;'" - Jp_
显示剩余8条评论

69
我在写Java代码时遇到了类似的问题。我的解决办法是给我不想提交的代码加上标记,然后添加一个预提交钩子来查找我的标记。
#!/bin/bash
#
# This hook will look for code comments marked '//no-commit'
#    - case-insensitive
#    - dash is optional
#    - there may be a space after the //
#
noCommitCount=$(git diff --no-ext-diff --cached | egrep -i --count "(@No|\/\/\s?no[ -]?)commit")
if [ "$noCommitCount" -ne "0" ]; then
   echo "WARNING: You are attempting to commit changes which include a 'no-commit'."
   echo "Please check the following files:"
   git diff --no-ext-diff --cached --name-only -i -G"(@no|\/\/s?no-?)commit" | sed 's/^/   - /'
   echo
   echo "You can ignore this warning by running the commit command with '--no-verify'"
   exit 1
fi

将以下内容放入.git/hooks/pre-commit中,并给予它chmod +x .git/hooks/pre-commit权限。

2
标记语言肯定比基于sed等的过滤解决方案更简单易懂和声明式。不错。 - user3275211
3
https://git-scm.com/docs/githooks#_pre_commit - TT--
1
如果可以的话,我会给这个点赞100次。这是一个安全而直接的解决方案。谢谢! - War Gravy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接