Subversion:防止对一个文件的本地修改被提交?

时间:2009-05-14 12:04:39

标签: svn

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

请注意,虽然我不想提交更改,但我希望在svn update时收到存储库中所做的任何更新。此外,只有在我的工作副本中,我不想将更改提交到该文件,其他用户不应受到影响。所以svn:ignore或提交钩子不符合我的目的。

目前,我只是这样做:

svn commit file1 file2...

我明确指定了包含的文件,但不包括我不想提交的特定文件。

然而,在我工作的时候,我养成了简单写作的习惯:

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

我担心在我没有注意的时候,我会无意中使用上面的命令提交“禁止”文件。

简而言之,我正在寻找的只是一种在工作副本中“标记”文件的方法,该方法可以防止Subversion提交该文件中的更改(即使我不是自动排除当我尝试提交所有文件时只是出错,这很好)。有点像标记处于“冲突”状态的文件...

这样的事情存在吗?

更新:akent,谢谢你指出这个very similar question

13 个答案:

答案 0 :(得分:17)

有一些答案可行:

  1. 创建一个预提交钩子脚本,在添加特定属性时拒绝提交。然后,您可以将此属性添加到工作副本中的文件以防止提交。
  2. TortoiseSVN将排除特殊更改列表中的文件“ignore-on-commit”。但是,这不受SVN命令行客户端的尊重。
  3. CoverosGene建议默认命令(例如svn commit)在默认更改列表上运行,这样如果您将文件分配给另一个更改列表,则可以排除该文件,但我在文档中找不到该文件的任何引用,在我的测试中这不起作用

    由于SVN命令行客户端没有很好的解决方案,我已经打开了一个增强请求here。该请求表明命令行客户端也可以遵守“ignore-on-commit”更改列表。

    更新:现在是issue 2858feature outline可以使用svn:hold属性处理它。

答案 1 :(得分:8)

我理解你遇到的问题;可能这个“禁止”文件包含仅与您的本地构建环境相关的配置设置等。我没有找到任何方法直接告诉SVN忽略版本化文件中的更改,但这是我过去使用过的解决方法。

假设您的文件被调用,比如说“build.conf”。将SVN版本化文件命名为build.conf.example。然后,在Makefile或构建脚本或其他任何内容中,您可以自动将build.conf.example复制到 real build.conf,它仍然是未版本控制的。然后你svn忽略build.conf,然后每个开发人员都可以对它进行任何本地更改。

但“必须有更好的方法”......

修改:此处几乎完全相同的问题:SVN: Is there a way to mark a file as "do not commit"?

答案 2 :(得分:8)

在其中创建一个包含该文件的changelist,然后不要注意更改列表。该文件将在那里等待提交,但是您的常规提交(在默认的更改列表中工作)将永远不会被提取。

svn changelist mylocal file1

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

答案 3 :(得分:5)

实际上,预提交脚本可以完成这项工作。

编写一个执行'svnlook diff'的预提交脚本,如果在变更集中设置了名为'nocommit'的属性,则拒绝提交。

然后,在您的工作副本中,您可以在任何不应提交的文件上设置'nocommit'属性。如果任何文件具有'nocommit'属性,则任何后续提交都将失败。如果您以后确实需要检查文件的更改,您只需从工作副本中删除'nocommit'属性。

答案 4 :(得分:4)

说到Tortoisesvn和更改列表,它已经附带了一个名为ignore-on-commit的更改列表,它可以满足您的需求。

答案 5 :(得分:3)

根据我的经验:不要将该文件置于版本控制之下并使用svn:ignore。

一开始有点难,因为你无法忽略已经完全受版本控制的文件,并且你无法从版本控制中删除文件而不将其从硬盘驱动器中删除(以及在下次更新时从每个工作副本中删除它)。 )。但是当你最终设法正确设置回购时,它就像魅力一样。不要忘记添加通用模板来代替原始配置文件(以便每个人都知道新的配置变量,等等)。

对于新的回购:

mkdir config
svn add config
svn propset svn:ignore '*.conf' config 

对于现有的repo:请确保在每个工作副本中备份配置,然后从repo中删除(svn del)config,commit(请注意:下次更新时,每个工作副本中的文件都将被删除) !你必须有一个备份),然后恢复文件并设置ignore属性。

另一种方式是锁定。它保证没有人提交文件,但是每次提交都会导致错误。不是很好。

第三种方式 - 变更集,SVN 1.5客户端的新功能。这很简洁,但它只与一个工作副本相关,而不是与全局存储库相关。而且你必须手动设置它们,添加每个新文件 - 它很难维护。

答案 6 :(得分:3)

在过去的几年里,我一直在使用一种简单的解决方案来实现您的目标。它被称为NOCOMMIT关键字。

我所做的是在我的SVN存储库中有一个预提交钩子,它检查是否有任何文件包含字符串NOCOMMIT,如果是,则提交失败。

因此,当程序员进行不应提交的修改时(例如,他们将项目范围的数据库连接字符串从公司范围的测试服务器更改为他们自己的本地测试服务器,或者他们添加了诊断调试语句,他们会以每秒数千行的速度向日志发送垃圾邮件。)他们会向其附加//NOCOMMIT条评论,而且他们不必担心意外提交。什么时候提交,他们被阻止,所以他们被迫:

  • 将该文件移至其不提交更改列表或
  • 搜索NOCOMMIT并删除它出现的任何内容,从而希望修复他们附加的代码。

就个人而言,我发现NOCOMMIT关键字非常有用,即使在处理我的宠物项目时也会使用它,显然,我是团队中唯一的程序员。

如果您使用的是Windows,则可以将以下文本粘贴到SVN存储库的pre-commit.bat文件夹中名为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; }

答案 7 :(得分:2)

Lock肯定不是你想要的,我认为任何内置功能都不适合你。

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

  1. 获取文件列表
  2. 删除我不想提交的内容
  3. 提交文件
  4. 有些事情:

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

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

答案 8 :(得分:2)

这个问题在Subversion FAQ。但如果您不控制存储库,答案就没那么有用了。

也许尝试在subversion之上使用git管理本地副本。有一个简单的course for git可用。然后,您可以使用git-svn来跟踪svn存储库中的更改以及提交更改。它需要一些学习和训练。

答案 9 :(得分:2)

如果您使用的是Windows,请使用TortoiseSVN。您可以将文件添加到special "ignore-on-commit" changelist,其行为完全如您所述。

答案 10 :(得分:1)

将所有文件添加到更改列表,然后删除您不想提交的文件。最后提交更改列表,如下所示:

$ svn status
M file01 
M ...
M file100
M file_not_ready_for_commit

// This will add all working copy files, can be adjusted to add only relevant files
$ svn changelist mychangelist -R .

// Remove the nascent one(s)
$ svn changelist mychangelist --remove file_not_ready_for_commit

// Commit only the files in the changelist
$ svn commit --changelist mychangelist

以上信息的来源是blog,其中还有http://svnbook.red-bean.com的链接以获取更多详细信息。所有归功于博客作者。

答案 11 :(得分:0)

您可以使用预提交挂钩。 在钩子中使用svnlook author来查看您是否是提交更改的人。如果是,请使用svnlook changed查看您是否正在更改其中一个禁用文件。

答案 12 :(得分:0)

您可以使用个人分支并切换该文件以获得此效果。 像这样:

 svn cp ^/trunk ^/branches/your_name -m "Creating a personal branch."    
 cd working_copy_of_trunk/sub_path/
 svn switch ^/branches/your_name/sub_path/your_file your_file

请注意:

  1. 您可以使用命令svn status
  2. 检查第五列中出现'S'的切换状态
  3. 您永远不会在分支上工作,您的working_copy_of_trunk仍然会与您已切换的文件之外的存储库中继目录同步,因此每当您对your_file提交更改时,该文件的提交将在您的分支上完成,而不是在中继线。
  4. 副本已完成服务器端,这是svn的推荐方法。完整的服务器端副本是即时的,不会在服务器上花费额外的空间。但是,还建议人们不要检查包含trunk / tags /和branches /的顶级目录,但是直接trunk /否则当从这个顶部dir更新时,所有文件都将在本地重复。如果是这种情况,则用第一个命令代替:

    svn cp --parents ^ / trunk / sub_path / your_file ^ / branches / your_name / sub_path / your_file

    最后,如果由于任何原因您不想将文件复制到存储库服务器上的其他位置,那么您仍然可以将此方法与外部服务器和svn:external关键字(不是真正推荐)结合使用。