Subversion:如何防止将本地修改的文件提交?

40

我有一个Subversion工作副本,在其中对一个文件进行了本地修改。这些修改只适用于我自己,我不想将它们提交。(仓库中的版本包含一些默认值,适合其他用户,但不适合我,这就是为什么我想在本地覆盖它们的原因。)

请注意,尽管我不想提交我的更改,但我希望在执行svn update时接收到仓库中的任何更新。此外,只有在我的工作副本中,我不想提交对该文件的更改,其他用户不应受到影响。因此,svn:ignore或提交钩子不符合我的目的。

目前,我只需执行以下操作:

svn commit file1 file2...

我希望能够明确指定有更改的文件,但排除我不想提交的特定文件。

然而在我工作时,我习惯于简单地写入:

svn commit -m "Log of what I just did"

我担心在不注意的时候,使用上述命令可能会无意中提交“禁止”文件。

简而言之,我想找到一种“标记”工作副本中某个文件的方法,以防止Subversion提交该文件的更改(即使只是在尝试提交所有文件时收到错误也可以)。就像标记处于“冲突”状态的文件一样...

这种方法是否存在?

更新:akent,感谢指出了这篇非常相似的问题


你的 IDE 能为你做到这点吗? - Josh
1
或者获取TortoiseSVN,它允许您选择要提交的文件。 - z -
4
什么是 IDE? :-) 我通常使用命令行中的 svn。 - Bruno De Fraine
13个回答

21

有几种方法可行:

  1. 创建一个 pre-commit 钩子脚本,当添加特定属性时拒绝提交。然后在工作副本中的文件中添加此属性以防止提交。
  2. TortoiseSVN 将排除特殊变更列表 "ignore-on-commit" 中的文件。但是,SVN 命令行客户端不会遵守此规则。

CoverosGene 建议默认命令如 svn commit 在默认 changelist 上操作,这样如果您将文件分配给另一个 changelist,则可以将其排除,但我在文档中没有找到任何相关参考,并且在我的测试中此方法不起作用

由于 SVN 命令行客户端没有好的解决方案,因此我已经打开了一个增强请求这里。该请求建议命令行客户端也应遵守 "ignore-on-commit" 变更列表。

更新:此问题现在是问题 2858,并且有一个功能概述来使用 svn:hold 属性进行处理。


还没有实现吗? - wonsuc
你好。svn:hold 已经实现了吗? - Andy Lin
1
目前(2020年1月),svn:hold仍未实现。 - Bruno De Fraine

10

在一个包含该文件的变更列表中创建一个changelist,然后只需要忽略这个变更列表即可。该文件将保持等待状态以进行提交,但是您的常规提交将不会捕获它,因为默认情况下工作在默认变更列表上。

svn changelist mylocal file1

将创建一个名为mylocal的更改列表,并将文件file1分配给它。


肯定是一个好的解决方案,但只适用于每个开发人员;不能为检出存储库的所有人设置。此外,仅在 SVN 版本 > 1.5 中可用。 - akent
8
变更清单看起来很酷,但你说的不完全正确:当我创建一个名为“mylocal”的变更清单时,“svn commit”仍会考虑所有修改过的文件。据我所见,文档中没有提到“默认”变更清单。 - Bruno De Fraine
正如Bruno De Fraine所说,changelists不会从提交中删除文件,并且没有忽略changelist的方法,尽管TortoiseSVN似乎有一个特殊的忽略changelist功能[请参见“从提交列表中排除项目”](http://tortoisesvn.net/docs/nightly/TortoiseSVN_en/tsvn-dug-commit.html)。 - zpon
不,我们只需要一个选项来 svn commit 并说“提交除了变更列表 X 之外的所有内容”...哦,Linus 对 SVN 的评价是正确的。 - Tomasz Gandor

9
我了解你遇到的问题;可能这个“forbidden”文件包含配置设置等,只与本地构建环境相关。我没有找到直接告诉SVN忽略版本控制文件中更改的方法,但这是我过去使用的一种解决方法。
假设你的文件名为“build.conf”。将SVN版本控制的文件命名为build.conf.example。然后,在你的Makefile或构建脚本中,可以自动将build.conf.example复制到未进行版本控制的实际build.conf中。然后你可以忽略build.conf,并且每个开发人员都可以对其进行任何本地更改。
但“肯定有更好的方法”... 编辑:几乎相同的问题在这里:SVN:是否有一种方法将文件标记为“不提交”?

1
显然,这也是常见问题解答中的答案。但是,这很麻烦,而且忽略了一个非常重要的问题:每当存储库中的“禁止”文件更新时,我希望svn up将远程更改与我的本地修改合并(必要时发出冲突信号)。对于未版本化的文件,您必须手动执行此操作,这意味着您的build.conf可能会与build.conf.example过时不符。 - Bruno De Fraine
同意,不是最理想的。CoverosGene的答案似乎是“更好的方法”。不过只在最近版本(1.5+)的SVN中才能使用。 - akent

6
实际上,可以使用预提交脚本完成该任务。
编写一个预提交脚本,执行 'svnlook diff' 命令,并在变更集中设置了名为'nocommit'的属性时拒绝提交。
然后,在你的工作副本中,只需要为任何不应提交的文件设置 'nocommit' 属性。如果有任何文件具有 'nocommit' 属性,则任何后续提交都将失败。如果以后确实需要在文件上检查更改,那么你只需从你的工作副本中删除 'nocommit' 属性即可。

5

提到TortoiseSVN和更改列表,它已经带有一个名为ignore-on-commit的更改列表,可以实现您想要的功能。


4
在过去的几年中,我一直在使用一个简单的解决方案,它可以完美地实现您所需要的功能。它被称为“NOCOMMIT”关键字。
我的做法是,在我的SVN仓库中设置一个pre-commit钩子,检查是否有任何文件包含字符串“NOCOMMIT”,如果有,则提交失败。
因此,当程序员进行修改时,(比如,他们将项目范围内的数据库连接字符串从公司范围的测试服务器更改为自己的本地测试服务器,或者添加了诊断调试语句,这些语句将每秒钟生成数千行日志),他们会在其后添加一个“// NOCOMMIT”注释,这样就不必担心意外提交它。当提交时间到来时,他们会被阻止提交,因此他们被迫要么:
- 将该文件移动到不提交的变更列表中,或者 - 搜索“NOCOMMIT”,并删除其中的任何出现,从而希望修复他们附加它的代码。
个人而言,我发现“NOCOMMIT”关键字非常有用,即使在我的小型项目中也是如此,显然,我是团队中唯一的程序员。
如果您正在使用Windows,则可以将以下文本粘贴到名为“pre-commit.bat”的文件中,并将其放入您的SVN存储库的“hooks”文件夹中。
:: Stops commits that contain the NOCOMMIT keyword.
setlocal  
set REPOS=%1  
set TXN=%2           
SVNLook diff %REPOS% -t %TXN% | findstr /I /M /L NOCOMMIT > nul
if %errorlevel% gtr 0 (
    exit 0
) else (
    echo Your commit has been blocked because it contains the keyword NOCOMMIT. 1>&2  
    exit 1
)

在Unix系统上,类似以下的代码应该可以解决问题,但请注意我没有进行过测试。
#!/bin/sh
REPOS="$1"
TXN="$2"
SVNLOOK=/usr/local/bin/svnlook
$SVNLOOK diff -t "$TXN" "$REPOS" | grep -i "NOCOMMIT" > /dev/null && { echo "Your commit has been blocked because it contains the keyword NOCOMMIT." 1>&2; exit 1; }

4
从我的经验来看:不要将该文件放入版本控制,并在其上使用svn:ignore。
一开始可能有些困难,因为您无法忽略已经处于版本控制下的文件,并且您无法在不从硬盘中删除文件(以及在下次更新时从每个工作副本中删除文件)的情况下从版本控制中删除文件。但是,当您终于成功设置存储库时,它就像魔法一样运行。别忘了添加通用模板以代替原始配置文件(以便每个人都知道新的配置变量等)。
对于新存储库:
mkdir config
svn add config
svn propset svn:ignore '*.conf' config 

对于现有的仓库:请确保在每个工作副本中备份您的配置,然后从仓库中删除(svn del)配置文件,提交更改(请注意:该文件将在下一次更新时在每个工作副本中被删除!您必须备份),然后恢复该文件并设置忽略属性。

另一种方法是锁定,它可以确保没有人提交该文件,但每次提交都会产生错误,不太好。

第三种方法是变更集,在 SVN 1.5 客户端中的一个新功能。这很方便,但只与一个工作副本相关,而不是全局的仓库。而且您必须手动设置它们,并添加每个新文件 - 维护起来很困难。


3

锁定肯定不是你想要的,我认为任何内置功能都不能满足你的需求。

根据你所在的环境,我会编写一个脚本:

  1. 获取文件列表
  2. 删除不需要提交的文件
  3. 提交文件

类似于以下内容:

svn status | grep ^M | grep -v exclude.c | awk -F' ' '{print $2}' | xargs svn ci -m "I'm committing something"

或者,如果文件列表真的很静态,只需修复列表!

3
这个问题在Subversion FAQ中有提到。但如果你没有控制存储库,答案就不是很有帮助。
也许可以尝试在Subversion之上使用git来管理本地副本。有一个简单的git课程可供学习。然后可以使用git-svn来跟踪svn存储库中的更改并提交您的更改。这需要一些学习和培训。

3

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