SVN:有没有一种方法可以将文件标记为“不提交”?

160

使用TortoiseSVN,我可以将文件移动到忽略提交清单中,这样当我提交整个目录树时,该文件的更改不会被提交。

是否有一种方法可以使用svn命令行工具做类似的事情?

编辑:感谢使用svn:ignore的建议,但那并不完全符合我的要求。

svn:ignore影响诸如svn addsvn import之类的事情。它提供了一个要忽略的文件名模式列表。

我有一个已经在源代码控制下的文件,但我想对该文件进行临时更改,这些更改以后在我提交整个源代码树时不想被提交。我正在进行许多其他更改,我可以在我的显示器上贴一个便条告诉我在提交树之前还原该文件,但如果svn可以自动跳过该文件,那就太好了。


1
有一种方法是使用个人分支和切换状态。 请参阅我在此主题上的其他帖子。 - ptitpion
18个回答

122
截至2016年2月/版本1.9,Subversion没有内置的“不提交”/“提交时忽略”的功能。这个答案是一个非理想的命令行解决方法。 正如OP所述,TortoiseSVN有一个内置的更改列表,“ignore-on-commit”,它会自动从提交中排除。由于命令行客户端没有这个功能,因此您需要使用多个更改列表来实现相同的行为(带有警告): - 一个用于您想要提交的工作[work] - 一个用于您想要忽略的内容[ignore-on-commit]
由于TortoiseSVN已经有了先例,我在我的示例中使用“ignore-on-commit”表示我不想提交的文件。我将使用“work”表示我想要提交的文件,但您可以选择任何名称。 首先,将所有文件添加到名为“work”的更改列表中。这必须从您的工作副本的根目录运行:
svn cl work . -R

这将递归地添加工作副本中的所有文件到名为“work”的更改列表中。这种方法有一个缺点-随着新文件被添加到工作副本中,您需要明确地添加新文件,否则它们将不会被包括在内。其次,如果您需要再次运行此操作,则需要重新添加所有“忽略提交”的文件。这并不理想-您可以像其他人一样开始维护自己的“忽略”列表文件。
然后,对于要排除的文件:
svn cl ignore-on-commit path\to\file-to-ignore

由于文件只能在一个变更列表中,因此在您之前的“工作”添加后运行此添加操作将从“工作”变更列表中删除要忽略的文件,并将其放入“提交时忽略”变更列表。

当您准备提交您希望提交的修改文件时,您只需在提交命令中添加“--cl work”:

svn commit --cl work -m "message"

以下是我的机器上一个简单示例的样子:

D:\workspace\trunk>svn cl work . -R
Skipped '.'
Skipped 'src'
Skipped 'src\conf'
A [work] src\conf\db.properties
Skipped 'src\java'
Skipped 'src\java\com'
Skipped 'src\java\com\corp'
Skipped 'src\java\com\corp\sample'
A [work] src\java\com\corp\sample\Main.java
Skipped 'src\java\com\corp\sample\controller'
A [work] src\java\com\corp\sample\controller\Controller.java
Skipped 'src\java\com\corp\sample\model'
A [work] src\java\com\corp\sample\model\Model.java
Skipped 'src\java\com\corp\sample\view'
A [work] src\java\com\corp\sample\view\View.java
Skipped 'src\resource'
A [work] src\resource\icon.ico
Skipped 'src\test'

D:\workspace\trunk>svn cl ignore-on-commit src\conf\db.properties
D [work] src\conf\db.properties
A [ignore-on-commit] src\conf\db.properties

D:\workspace\trunk>svn status

--- Changelist 'work':
        src\java\com\corp\sample\Main.java
        src\java\com\corp\sample\controller\Controller.java
        src\java\com\corp\sample\model\Model.java
M       src\java\com\corp\sample\view\View.java
        src\resource\icon.ico

--- Changelist 'ignore-on-commit':
M       src\conf\db.properties

D:\workspace\trunk>svn commit --cl work -m "fixed refresh issue"
Sending        src\java\com\corp\sample\view\View.java
Transmitting file data .done
Committing transaction...
Committed revision 9.

另一种方法是将您希望提交的每个文件都添加到“工作”变更列表中,甚至不需要维护忽略列表,但这也很麻烦。实际上,唯一简单理想的解决方案是如果/当SVN本身实现了此功能。在Subversion问题跟踪器中有一个长期存在的问题SVN-2858,如果将来发生更改,则会进行更新。


1
我已经使用你提到的命令添加了两个文件:`$svn st--- Changelist 'ignore-on-commit': M database.php M config.php ` 但是,在提交时它们仍然被发送到了仓库。你有什么想法,我做错了什么吗? - Attila Fulop
7
将文件添加到“ignore-on-commit”更改列表并不会阻止这些文件被提交。TortoiseSVN(Windows GUI客户端)内置了对"ignore-on-commit"的尊重,但命令行svn没有。我原始答案中唯一的建议是将要提交的文件添加到一个更改列表中,并告诉它提交该列表。 - Joshua McKinnon
7
ignore-on-commit 明确是 TortoiseSVN 保留的列表,它只是默认情况下防止项目在图形用户界面中被检查,因此它是一个特定于 TortoiseSVN 的 GUI 功能。如果您使用 GUI,则不需要使用命令行来添加到列表中。只需在提交列表项上下文菜单中,在底部您可以将它们移动到一个更改列表,并且 ignore-on-commit 已经被定义。http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-changelists.html - tjmoore
这个没干什么。它提交了所有东西。 - ahnbizcad
不起作用,问题明确要求命令行解决方案,而不是图形用户界面。 - riv

26

我也经常遇到这种情况:变更列表对我不起作用 - 我想要创建一个文件的简短列表,这些文件我不想提交,而不是维护一个庞大的文件列表,这些文件我希望能够提交!

我在Linux命令行上工作:所以我的解决方案是创建一个名为 /usr/bin/svnn 的脚本(是的,有两个“n”!),内容如下:

#! /bin/bash
DIR=/home/mike/dev/trunk

IGNORE_FILES="\
        foo/pom.xml \
        foo/src/gwt/App.gwt.xml \
        foo/src/main/java/gwt/Common.gwt.xml \
        foo/src/main/resources/context/datasource/local.xml \
        foo/src/main/resources/context/environment/local.xml"

for i in $IGNORE_FILES; do mv $DIR/$i $DIR/"$i"_; done;

svn "$@"

for i in $IGNORE_FILES; do mv $DIR/"$i"_ $DIR/$i; done;

很明显,这是根据我的情况定制的 - 但只需更改 DIR 和 IGNORE_FILES 以适应您的开发设置即可。请记得使用以下命令使脚本可执行:

sudo chmod +x /usr/bin/svnn

如果您使用“svnn”而不是“svn”来运行Subversion,则无需担心将本地更改检入IGNORE_FILES列表中的文件。 希望这可以帮助您!


最后,这个答案是正确的。你需要编写一些工具。这还不够完美,因为我想要一个动态选项,比如 svnn ignore configs/* - 带有通配符和其他功能。我想我会自己写类似的东西,然后再回来! - Tomasz Gandor
这太棒了!更好的是,在.bashrc中为svn创建一个别名-> svnn。更好的是,它不需要在命令中指定要忽略的文件,而是可以像git一样,检查文件夹内的.ignore文件,并忽略与模式匹配的每个文件。 - Tarek
不必重新学习输入“svnn”,考虑将其命名为“svn”,并将此脚本放置在您的PATH开头的某个位置,例如${HOME}/bin。然后从脚本本身调用/usr/bin/svn - Joost

19

我不认为有一种方法可以忽略存储库中的文件。我们经常在web.config和其他配置文件中遇到这个问题。

虽然不完美,但我最常见和使用的解决方案是使用.default文件和nant任务创建本地副本。

例如,在存储库中有一个名为 web.config.default 的文件,其中包含默认值。然后创建一个nant任务,将所有的web.config.default 文件重命名为可以自定义为本地值的web.config文件。当获取新的工作副本或运行构建时应该调用此任务。

您还需要忽略所创建的web.config文件,以便它不会提交到存储库中。


8
请查看变更列表,它可以为您提供一种过滤您已更改但不想提交的文件的选项。 SVN不会自动跳过文件,除非您告诉它如何 - 而告诉它这个文件与其他文件有所不同的方法是将其放入变更列表中。
这需要更多的工作,而且你只能将变更列表应用于你的工作副本(显然,如果你可以将“永远不更新”属性应用于修订版,那么可能会导致混乱!)。

1
但这正是我们想要的。例如,一个源文件,你需要设置defaultUserId = yourId,而不是系统默认值。 - orbfish

4

我来到这个线程是为了找一个只提交某些文件的 "原子" 提交方法,而不是在提交时忽略一些文件。最终,我选择了只提交我想要的文件:

svn ci filename1 filename2

也许,这会对某些人有所帮助。

你的回答是这个帖子中唯一合适的建议。svn ci 只是 svn commit 的别名。Commit 命令允许对指定文件进行特定的提交。 - oxfn

3

大家好,我找到了一个解决方案。鉴于TortoiseSVN的工作方式符合我们的要求,我尝试在Linux上安装它 - 也就是说,在Wine上运行。令人惊讶的是,它可以工作!您需要做的只是:

  1. 通过运行“svn changelist'ignore-on-commit'”添加要跳过提交的文件。
  2. 使用TortoiseSVN提交:“~/.wine/drive_c/Program\ Files/TortoiseSVN/bin/TortoiseProc.exe /command:commit /path:'
  3. 默认情况下,排除的文件将被取消选中以进行提交,而其他修改的文件将被选中。这与Windows下完全相同。享受吧!

(之所以需要通过CLI排除文件是因为找不到执行此操作的菜单项,不确定原因。无论如何,这个方法很棒!)


2
您可以直接通过TortoiseSVN配置“忽略提交”变更列表,无需配置其他变更列表,包括所有其他文件。
1) 单击“SVN提交…”(我们不会提交,只是为了找到图形菜单以设置变更列表) 2) 在列表上右键单击要排除的文件。 3) 菜单:移动到变更列表 > 忽略提交。
下一次进行“SVN提交…”时,这些文件将出现在列表末尾未选中,并显示为“忽略提交”类别下的文件。
测试过程使用的软件版本信息如下: TortoiseSVN 1.8.7, Build 25475 - 64位, 2014/05/05 20:52:12, Subversion 1.8.9, -release。

1
你好,我刚看到tjmoore的评论,已经为TortoiseSVN用户提供了很好的信息...无需使用命令行 https://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-changelists.html - luney
这在1.9版中有问题吗? - Jake Hm

2
不允许提交冲突文件。你可以利用这一点将私人更改保留在仓库之外。对于少量文件,这种方法效果最佳。
要使a-file出现冲突,你的工作副本(WC)没有来自仓库的最新a-file,并且你的WC中的a-file有与仓库中相同位置的更改(你还没有更新的更改)。如果你不想等待上述条件,你可以按照以下方式创建a-file的冲突:
在工作副本1(WC1)中,在a-file顶部添加一行文本,例如"make a conflict here"。使用必要的语法,以避免破坏仓库。从WC1提交a-file。在WC2中,在a-file顶部添加另一行不同的文本,如"i want a conflict"。从WC2更新,现在a-file应该处于冲突状态。

1
这可能有点晚了,但我找到了一个非常棒的命令行命令来解决这个问题。使用bash完成。享受吧。
svn status | grep -v excluding | sed 's/^A */"/g; s/$/"/g' | tr '\n' ' ' | xargs svn commit -m "My Message"

好的,这里是命令的解释。根据您的使用情况,可能需要进行一些更改。

svn status

我获得了所有文件的列表。它们都以状态字符(?,!,A等)开头。每个文件独占一行。
grep -v excluding

我使用grep来过滤列表。它可以正常使用(包含)或使用-v标志(排除)。在这种情况下,它被用于排除,短语“excluding”将被排除。
sed 's/^. */"/g; s/$/"/g'

现在我使用sed删除每行开头的状态字符和空格,然后引用每一行。由于我的一些文件名中有空格,因此需要进行引用。

tr '\n' ' '

使用 tr 命令,我将所有的换行符替换为空格。现在我要提交的文件列表全部在一行上。
xargs svn commit -m "My Message"

最后,我使用xargs执行我的提交命令并带上消息。它会提交,并将我的引用文件列表作为最后一个参数丢弃。
结果是一切都最终按照我想要的方式运行。我仍然有点讨厌svn迫使我跳过这些该死的环节,但我可以接受。我想。

1
我厌倦了等待SVN自带此功能。我曾使用带有ignore-on-commit的TortoiseSVN,但它会弹出用户对话框,无法从命令行中抑制。当我运行构建脚本并去泡杯茶时,我讨厌回来后发现它在10%的进度处等待用户输入。
因此,这是一个Windows PowerShell脚本,仅提交不在更改列表中的文件:
# get list of changed files into targets
[XML]$svnStatus = svn st -q --xml C:\SourceCode\Monad
# select the nodes that aren't in a changelist
$fileList = $svnStatus.SelectNodes('/status/target/entry[wc-status/@item != "unversioned"]') | Foreach-Object {$_.path};
# create a temp file of targets
$fileListPath =  [IO.Path]::GetTempFileName();
$fileList | out-file $fileListPath -Encoding ASCII
# do the commit
svn commit --targets $fileListPath -m "Publish $version" --keep-changelists 
# remove the temp file
Remove-Item $filelistPath

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