如何永久阻止文件的特定部分在git中提交?

时间:2012-06-20 08:43:02

标签: git git-svn gitignore

我用git-svn克隆了一个远程SVN存储库。我已经以代码编译的方式修改了这个克隆仓库中的pom.xml文件。此设置仅供我使用。因此,我不想将更改推回到远程仓库。

有没有办法阻止文件的这种(部分)更改被提交到repo中?我知道这个事实,我可以使用个人分支,但这意味着某些合并开销。还有其他方法吗?

我已经调查过这个questionone,但它们只是暂时的变化。

更新:我也知道.gitignore的可能性,但这意味着完全排除文件。

6 个答案:

答案 0 :(得分:2)

编辑:你问的是不可能的,我没有看到“部分”部分。 我知道你只能提交部分文件,但你不能忽略文件的某些部分。 您将需要使用更新索引技巧以避免将其置于“状态”中,并且每次从远程转换/合并时都需要存储该文件,然后取消修改并忽略您的更改 - 指数。 我不知道你是否可以为一系列git命令创建一个git别名,所以用一个命令可以完成所有这3个命令以避免麻烦

使用.gitignore文件,也不要将其推送到远程仓库:Ignore the .gitignore file itself

在.gitignore中,你应该

 .gitignore
 path/to/pom.xml

.gitignore文件可以位于工作树的根目录,也可以位于您想要/需要的任何子目录中

答案 1 :(得分:2)

共享这种配置文件的一种通用方法是:

  1. 提交模板文件(例如:pom.xml.template
  2. 忽略文件本身(例如:将pom.xml添加到.gitignore文件中)
  3. 让每个用户都可以根据自己的需要自定义此文件

一些实现步骤3的方法是:

  • 让用户手动编辑并复制模板文件并对其进行编辑
  • 具有一些脚本,该脚本在模板文件上应用替换并将输出写入预期的目标

答案 2 :(得分:1)

过滤器可能存在可能性。但这需要进一步探讨。

起点:为此过滤器实施涂抹/清洁:

c = C*c + (A*op(a))*(B*op(b))
c = C*c + A*(op(a))*B)*op(b)
c = C*c + A*(B*op(a))*op(b)
c = C*c + (A*B)*op(a)*op(b)

这样,比较时文件总是相同的,因为应用了过滤器。

问题:仍然需要调查如何找回过滤后的文件。这在工作目录中并不明显。

Smudge clean filter

答案 3 :(得分:1)

在git之外解决问题可能更容易。 您可以在pom.xml中使用默认值定义属性, 每个人都使用的。 对于独家设置,您只需使用${user.home}/.m2/settings.xml-Dproperty=value或maven命令行中覆盖属性。 或者类似地,您可以创建另一个配置文件并根据您导出的环境变量(例如〜/ .bashrc)来激活它。

对于git解决方案,我通过遵循正确的工作流程来遵循一定的纪律来完成您想要的工作:

  1. 对pom.xml(或其他文件)进行特定于设置的更改。
  2. 将更改提交到git中(仅限本地)。在提交标题/消息中声明所做的更改仅供本地使用,例如“仅限本地使用。请勿DCOMMIT:标题的其余部分”。
  3. 从svn中拉出更改,进行本地git提交等。
  4. 是时候该将您的更改重新提交回svn了,
    1. git svn rebase从SVN中提取新提交,解决冲突。
    2. git rebase -i svn/trunk(或您的svn远程分支)(这将在SVN的基础上开始对所有本地更改进行交互式重新存储)
    3. 在交互式rebase todo编辑器中,将仅本地提交移到底部。
    4. 保存待办事项并退出rebase待办事项编辑器。
    5. 解决所有冲突(除非您在其他本地提交中触摸pom.xml(或其他本地文件)的相同部分,否则应该没有冲突。
  5. 运行git svn dcommit --dry-run @~1(或在旧版git中运行git svn dcommit --dry-run HEAD~1),以查看将要推送到SVN存储库的内容;确保您的仅本地提交不在列表中。
  6. 运行git svn dcommit @~1(或git svn dcommit HEAD~1)以最终将更改推送到SVN存储库。
  7. git svn rebase从SVN中提取新提交。

这听起来很复杂,但是一旦您习惯了它就非常简单。基本上,您有一个(或多个)本地提交,而您从未将它们提交到SVN。使用此具有多个提交和存储库的工作流,一年多来我都没有错误地推送提交。例如,对某些仅用于调试的本地更改非常有用(尽管最好为此引入一个环境变量或一些设置文件)。

此外,可以使用git中的预提交钩子来增强此功能,这将确保不对仅本地更改进行提交。不幸的是,我没有看到标准的git-svn钩子,但是可以使用git-svn-hooks来实现这些钩子。

答案 4 :(得分:1)

在我看来,这是预提交挂钩的有力例证。在.git文件夹中,您应该有一个hooks文件夹。它可能有一些样本,但是由于它们具有.sample扩展名而被忽略。如果添加包含以下脚本的名为“ 预提交”(无扩展名)的文件,则该脚本将在每次提交时运行。不要忘记通过运行“ chmod ug + x pre-commit ”使脚本可执行。

我添加了一些注释来解释每行的用途,但实际上,您将如何使用它,是将' #start '放在不需要包含的代码上方您的git提交,然后在该代码下方“ #end ”。您可以在sed命令中使用不同的开始和结束标志,只需确保对要开发的任何语言都使用注释语法,以便编译器将其忽略。当您最终执行提交时,将发生以下情况:

  1. 中间的代码(包括#start和#end标志)将被删除
  2. 该文件将在没有代码和标志的情况下提交
  3. 代码和标志将返回到文件的本地副本

由于这些都包含在预提交钩子中,因此每次您提交时,这些都会自动发生。

预提交

#!/usr/bin/env bash

echo "Running pre-commit hook..."

set -e
export PATH=$PATH:/usr/local/bin
exit_status=0

echo "Removing supercomments..."
# Get a list of files part of this commit
files=$(git diff --cached --name-status)

# Loop through each file
for f in $(echo $files | awk '{ print $2}')
do
        # Create a temp copy of the file
        cp ${f} ${f}.temp
        # Remove all chunks between '#start' and '#end'
        sed -i '/#start/,/#end/d' ${f}
        # Add the file with chunks removed
        git add ${f}
        # Replace file with temp file containing code you didn't want to comm
it
        cp ${f}.temp ${f}
done

echo "Hook completed!"

exit $exit_status

用法示例:

test.txt

This is a file
It's really just a test file

#start
This code is only relevant to me
When I eventually commit this file...
...please don't inclue all of this!
#end

This part of the file is important,
make sure it's included in my next commit.

添加并提交test.txt:

git add test.txt
#

git commit -m "A great commit message."
# Running pre-commit hook...
# Removing supercomments...
# Hook completed!
# [master commit_id_1234] A great commit message.

test.txt(在commit_id_1234 中为

This is a file
It's really just a test file


This part of the file is important,
make sure it's included in my next commit.

test.txt(提交后的本地副本

This is a file
It's really just a test file

#start
This code is only relevant to me
When I eventually commit this file...
...please don't inclue all of this!
#end

This part of the file is important,
make sure it's included in my next commit.

注意: 您的问题需要考虑一些细微差别。听起来您有文件要保存在文件中的一组代码,但是仅在本地编译时才用(我假设您主要在本地开发和测试代码),但是随后您希望能够提交该开发代码并在提交之前,系统会自动删除您的“ 仅本地相关代码”。尽管上面的钩子应该做到这一点,但请记住,“ 仅本地相关代码”部分并未进行版本控制,因为在最终推送时它从未触及远程存储库。这可能很明显,但是只需确保您对此表示满意即可。如果您的本地副本出了点问题,那么所有这些代码(即使仅与您相关)也可能会丢失,并且仅通过重新克隆存储库就无法恢复。

答案 5 :(得分:0)

已经提出了好主意。前叉似乎最合适。需要考虑的其他一些方法是: -分叉仓库并提交所有更改 -在同一仓库中提交一个单独的分支,并提交 -是否有一个仅由您的私人差异组成的本地分支机构,您在结帐时会挑选樱桃,然后在办理登机手续之前撤消? -应用补丁文件-再次签入,可以在签入之前撤消(虽然有问题)