Subversion:阻止本地修改一个文件被提交?
我有一个Subversion工作副本,我对一个文件进行了一些本地修改。 修改只与我有关,我不想提交。 (版本库中的版本包含一些适用于其他用户的默认值,只是不适合我,这就是为什么我想在本地覆盖它们的原因。)
请注意,尽pipe我不想提交我的更改,但是在执行svn update
时,我确实希望接收存储库中所做的任何svn update
。 此外,只有在我的工作副本中,我不想对该文件进行更改,其他用户不应受到影响。 所以svn:ignore
或提交钩子不符合我的目的。
目前,我只是做:
svn commit file1 file2...
在那里我明确指定的文件有变化, 不包括我不想提交的特定文件。
但是,在我工作的时候,我有一个简单的写作的习惯:
svn commit -m "Log of what I just did"
我担心在我不注意的时候,我会不经意地使用上述命令来犯下“禁止”的文件。
简而言之,我正在寻找的只是一种“标记”工作副本中的文件的方式,它可以防止Subversion提交该文件中的更改(即使只是获得一个文件,也不必自动排除)错误,当我尝试提交所有文件,这是好的)。 有点像标记文件在“冲突”状态…
这样的事情存在吗?
更新 :非常感谢您指出这个非常类似的问题 。
有几个答案可以工作:
- 创build一个预先提交的钩子脚本,在添加特定属性时拒绝提交。 然后,您可以将此属性添加到工作副本中的文件以防止提交。
- TortoiseSVN将排除特殊更改列表“ignore-on-commit”中的文件。 但是,这并不是SVN命令行客户端的荣幸。
CoverosGenebuild议像svn commit
这样的默认命令在默认的更改列表上svn commit
操作,这样,如果将文件分配给其他更改列表,则可以排除该文件,但是在文档中找不到任何文件的引用,并且在testing中不起作用 。
由于SVN命令行客户端没有很好的解决scheme,我在这里打开了一个增强的请求。 该请求表明,命令行客户端也可以遵守“忽略提交”更改列表。
更新:这是现在的问题2858 ,有一个function大纲来处理它与svn:hold
属性。
在其中创build一个包含该文件的更改列表 ,然后只是不注意更改列表。 该文件将等待提交,但是您的常规提交(在默认更改列表中工作)将永远不会提取。
svn changelist mylocal file1
将创build一个名为mylocal
列表,并将文件file1
分配给它。
我明白你的问题; 可能这个“禁止”文件包含configuration设置等只与您的本地生成环境相关。 我还没有find任何直接告诉SVN忽略版本化文件中的变化的方法,但是这是我以前使用过的解决方法。
假设你的文件被调用,比如说“build.conf”。 将这个SVN版本化的文件命名为build.conf.example。 然后,在你的Makefile或者构build脚本或者其他的东西里,你可以自动的将build.conf.example拷贝到真正的 build.conf文件中去, 然后,你svn忽略build.conf,然后每个开发人员可以做任何他们需要的本地更改。
但是“一定有更好的办法”…
编辑:几乎相同的问题在这里: SVN:有没有办法将文件标记为“不提交”?
实际上,一个预先提交的脚本可以完成这项工作。
编写一个执行“svnlook diff”的预先提交脚本,如果在变更集中有一个名为“nocommit”的属性,则拒绝提交。
然后,在你的工作副本中,你可以在任何不应该提交的文件上设置'nocommit'属性。 如果任何文件具有“nocommit”属性,则任何后续提交都将失败。 如果以后确实需要检查文件中的更改,则只需从工作副本中删除“无法提交”属性即可。
说起Tortoisesvn和changelists,它已经有了一个名为ignore-on-commit的变更列表,它可以做你正在寻找的东西。
根据我的经验:不要将该文件放在版本控制下,并使用svn:ignore。
开始的时候有点难,因为你不能忽略版本控制下的allready文件,而且你不能从版本控制中删除文件,也不能从硬盘(以及下一次更新中的每个工作副本)中删除文件。 但是,当你最终设法正确地设置回购,它就像魅力。 不要忘了添加一个通用模板来代替原来的configuration文件(这样每个人都知道新的configurationvariables,等等)。
对于新的回购:
mkdir config svn add config svn propset svn:ignore '*.conf' config
对于现有的回购:确保在每个工作副本中都有备份你的configuration,然后从回购中删除(svn del)configuration,提交(请注意:下次更新时,每个工作副本中的文件都将被删除!备份),然后恢复文件并设置忽略属性。
另一种方法是locking。 它保证没有人提交文件,但是每次提交都会导致错误。 不大好。
第三种方式 – 变更集,SVN 1.5客户端中的一项新function。 这是整洁的,但它只涉及到一个工作副本,而不是全球存储库。 而且你必须手动设置它们,添加每个新文件 – 很难维护。
locking肯定不是你想要的,我不认为任何内置的function将为你做。
根据你正在工作的环境,我会写一个脚本:
- 获取文件列表
- 删除那些我不想提交的
- 提交文件
有些东西是:
svn status | grep ^M | grep -v exclude.c | awk -F' ' '{print $2}' | xargs svn ci -m "I'm committing something"
或者,如果文件列表真的是静态的,只需修复列表!
如果你在Windows上,使用TortoiseSVN。 您可以将文件添加到特定的“ignore-on-commit”更改列表中 ,该更改列表的行为与您所描述的完全相同。
这个问题在Subversion FAQ中 。 但是,如果您不控制存储库,答案不是很有用。
也许尝试在颠覆之上用git来pipe理你的本地副本。 git有一个简单的过程 。 然后,您可以使用git-svn来跟踪svn存储库中的更改并提交更改。 这将需要一些学习和培训。
在过去的几年中,我一直在使用一个简单的解决scheme,实现你正在寻找的东西。 它被称为NOCOMMIT
关键字。
我所做的是我的SVN仓库中有一个预先提交的钩子,它检查是否有任何文件包含stringNOCOMMIT
,如果是,则提交失败。
所以,当一个程序员进行一个不应该被提交的修改时,(比如说,他们把整个项目范围的数据库连接string从公司范围的testing服务器改为他们自己的本地testing服务器,或者他们添加了诊断debugging语句,以每秒数千行的方式发送垃圾邮件),他们会附加一个//NOCOMMIT
注释,而且不必担心意外提交。 当时间到了,他们被阻止,所以他们被迫:
- 将该文件移动到他们的不提交更改列表或
- search
NOCOMMIT
并删除它的任何事件,从而希望修复他们已经附加的代码。
就我个人而言,我发现NOCOMMIT
关键字非常有用,甚至在我的宠物项目上也使用它,显然,我是团队中唯一的程序员。
如果你使用的是windows,你可以把下面的文本粘贴到SVN仓库的hooks
文件夹中的pre-commit.bat
文件中。
:: 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系统上,像下面这样的东西应该可以做到,但是请注意我还没有testing过。
#!/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; }
你可以使用预先提交的钩子。 在钩子中使用svnlook author
来看看你是否是一个提交更改。 如果是这样,使用svnlook changed
,看看你是否正在改变一个禁止的文件。
您可以使用个人分支并切换该文件以达到此效果。 喜欢这个:
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
注意:
- 您可以用命令:
svn status
检查第五列上出现的'S'的切换svn status
- 你永远不会在分支上工作,你的working_copy_of_trunk仍然与库中的trunk目录同步,除了你已经切换的文件之外,所以无论何时在your_file上提交修改,这个文件的提交都会在你的分支上完成,而不是在中继上完成。
-
副本已经完成了服务器端,这是svn推荐的方式。 完整的服务器端副本是即时的,不会在服务器上花费额外的空间。 但是,也build议人们不要检出包含trunk / tags /和branches /的最前面的目录,而是直接中继/否则当从这个top dir更新时,所有的文件都会在本地复制。 如果是这种情况,则用下面的命令代替第一个命令:
svn cp –parents ^ / trunk / sub_path / your_file ^ / branches / your_name / sub_path / your_file
最后,如果出于任何原因,你不想复制你的文件在你的存储库服务器上的其他地方,那么你可能仍然将这种方法与外部服务器和svn:external关键字(不是真的推荐)结合起来。
将所有文件添加到更改列表中,然后删除不想提交的文件。 最后提交更改列表如下所示:
$ 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
以上信息的来源是这个博客 ,也有链接到http://svnbook.red-bean.com进一步的细节。; 所有的信贷给博客的作者。