从Subversion检出一个文件

343

无法单独检出一个文件。您可以进行的最精细级别的检出是在目录级别。

使用Subversion时,我该如何解决这个问题?

我们在Subversion中有一个文件夹,用于存放所有的图片。我只想从中检出一个文件(图像)。这个文件夹非常大,还有很多其他我现在不需要的东西。


你可以用另一种方式来完成。登录到生产服务器,然后在计算机上的本地目录中执行 svn up 命令。 - Neocortex
19个回答

424
简单来说,您需要使用 svn export 导出文件而不是检出文件。但这可能不是您想要的。您可能希望在不必下载您不需要的大量垃圾文件的情况下,在文件上进行操作并将其检入。如果您使用的是Subversion 1.5+,则可以进行稀疏检出。
svn checkout <url_of_big_dir> <target> --depth empty
cd <target>
svn up <file_you_want>

对于旧版的SVN,你可能会从以下内容中获益:

  • 使用远古时期的修订版本检出目录,此时该目录不会包含太多你不需要的垃圾文件。
  • 更新你想要的文件,以创建混合修订版本。即使该文件在你检出的修订版本中不存在,这也是可行的。
  • 受益!

另一种选择(例如,如果目录从创建时就包含了太多垃圾)是将所需文件从URL->URL进行复制,放入存储库中的新位置(实际上这是文件的工作分支)。检出该目录并进行修改。

我不确定是否可以在没有目标工作副本的情况下完全将修改后的副本合并回存储库-我从未需要这样做过。如果可以,那么就这样做。

如果不行,那么不幸的是,你可能需要找到其他人已经检出整个目录并让他们来完成它。或者当你完成你的修改时,其余部分可能已经下载完了......


14
最简单的解决方法是用网页浏览器访问代码库。 - dolmen
11
假设您不需要修改文件,并且假设该存储库有一个Web界面正在运行,则可能更简单的方法是使用“svn export”而不是使用Web界面,如果我知道我想要哪个文件。 问者已经在使用SVN,所以这取决于客户端和该客户端是否轻松使用“svn export”。但是,在浏览方面,我确实发现Web界面比“svn ls”更好用。 - Steve Jessop
2
如果您的Subversion服务器支持,SmartSVN客户端将锁定单个文件。还有一些钩子需要在检入二进制/可执行文件之前进行检出。让两个人修改一个二进制文件并合并这些更改似乎没有意义。这些可能是此问题提出时不可用的新功能。 - TamusJRoyce
@Tamus:“它没有真正意义。”同意,但在我描述的情况下,合并只是为了将新版本放回原始位置。不会预期二进制文件在合并目标中被修改。因此,文件本身不需要任何“合并”操作,只需用新文件替换旧文件即可。这仅仅是SVN把它称之为合并,并记录变化来自何处以供参考。你是对的,可以通过在持续时间内锁定文件来实施冲突避免。 - Steve Jessop
1
TortoiseSVN可以检出单个文件。我相信它在幕后做了同样的事情来实现这一点。 - Mike Starov
显示剩余3条评论

118

尝试使用svn export代替svn checkout。对于单个文件有效。

限制的原因是checkout会创建一个工作副本,其中包含有关存储库、修订版本、属性等元信息。这些元数据存储在名为“.svn”的子目录中。而单个文件没有子目录。


2
注意:极老版本的 svn 无法进行单个文件的导出。 - Mladen Jablanović
5
如果你只是想在部署过程中抓取特定脚本的最新版本,那么这是一种更优越的方法。 - william.berg
3
即使在2011年,那个警告也有些牵强,但是极老版本的SVN可以使用svn cat $url_to_file_in_repo > $local_file_name命令。 - cprn
我更喜欢使用svn export而不是先使用svn checkout再跟着使用svn up,因为使用svn export时不会检出任何元数据。 - mihca

55

使用svn catsvn export命令。

这样做,您无需获取工作目录,但将无法提交所做的任何更改。如果您需要进行更改并提交它们,则需要一个工作目录,但您不必完全获取它。检出目录仍然/几乎为空的修订版本,然后使用“svn cat”从HEAD中提取文件。


svn cat svn://.../my_file.txt正是我所需要的。我在一个只有svn://(没有http://)的代码库中工作,最新的websvn界面似乎不提供原始文件下载(或者我们配置错误或者我太瞎了)。这种方式比为了下载一个文件而进行checkout+up更加简单。 - ribamar

15

您可以分两步来完成:

  1. 检出一个只有元信息的空SVN仓库:

  2. $ cd /tmp
    
    $ svn co --depth empty http://svn.your.company.ca/training/trunk/sql
    
    运行svn up命令来更新指定的文件:
    $ svn up http://svn.your.company.ca/training/trunk/sql/showSID.sql
    

这似乎是一种简单的方法。但对我来说并没有起作用,因为我想要的文件是一个软链接。所以当我执行 svn up <url>/softlinkfile 时,它被 svn 跳过了。 但当我们不想要整个目录时,这肯定是一种整洁的方式。 - Lokesh Purohit

12
如果您想在不检出它的情况下查看您存储库中的readme.txt文件: $ svn cat http://svn.red-bean.com/repos/test/readme.txt 这是一个README文件。你应该阅读它。 提示: 如果您的工作副本过时(或您有本地修改),并且您想在您的工作副本中查看文件的HEAD修订版,svn cat将在给定路径时自动获取HEAD修订版: $ cat foo.c 此文件位于我的本地工作副本中,并具有我所做的更改。 $ svn cat foo.c 最新版本从存储库刷新! 来源

您也可以直接使用任何HTTP客户端,例如您的Web浏览器或命令行工具,如“curl”或“wget”。 - dolmen

9
以下是被接受答案的TortoiseSVN等效解决方案(我在公司的内部文档中写了这篇文章,因为我们正在新采用SVN)。我认为在这里分享会很有帮助:
检出单个文件: Subversion不支持检出单个文件,它只支持检出目录结构。(参考:http://subversion.tigris.org/faq.html#single-file-checkout)。这是因为每个作为工作副本检出的目录都将修改/文件版本的元数据存储为内部隐藏文件夹(.svn/_svn)。目前(v1.6)单个文件不支持此功能。 备选推荐策略:您只需要执行一次检出目录部分,之后您可以直接检出单个文件。对父文件夹和目录结构进行稀疏检出。稀疏检出基本上只检出文件夹结构而不填充内容文件。因此,您只需检出目录结构,无需像之前那样检出所有文件。
参考:http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-checkout.html 步骤 1:进入存储库浏览器。 步骤 2:右键单击存储库中包含您要处理的所有文件的父文件夹,并选择“检出”。 步骤 3:在新的弹出窗口中,确保检出目录指向您本地 PC 上的正确位置。还将有一个名为“检出深度”的下拉菜单。根据您的需求选择“仅此项”或“立即子项,包括文件夹”。建议选择第二个选项,因为如果您想要处理嵌套文件夹,您可以直接进行下一步,否则您将不得不为嵌套文件夹再次执行整个过程。
步骤 4:父文件夹现在应该在您选择的本地文件夹中可用,并且正在使用 SVN 进行监视(一个隐藏的文件夹“.svn”或“_svn”现在应该存在)。现在,在存储库中,右键单个要检出的文件,然后选择“更新项目到修订版”选项。现在可以对单个文件进行操作并将其检入存储库。
希望这有所帮助。

6

如果您所需要的内容可以通过将文件包含在另一个文件夹的检出中来实现,那么可以进行更新。

从 SVN 1.6 开始,您可以使用“文件外部定义”(file externals) ,这是一种 svn 链接。这意味着您可以有另一个带有单个文件的版本化文件夹。在此文件夹的检出中提交更改到该文件也是可能的。

很简单,检出您想要包含文件的文件夹,然后向文件夹添加一个属性即可。

svn propedit svn:externals .

带有这样内容的代码:

file.txt /repos/path/to/file.txt

提交后,该文件将出现在文件夹的未来检查中。基本上它是有效的,但如上面链接的文档中所述,存在一些限制。

5
cd C:\path\dir
svn checkout https://server/path/to/trunk/dir/dir/parent_dir--depth empty
cd C:\path\dir\parent_dir
svn update filename.log

(编辑filename.log)

svn commit -m "this is a comment."

4

做这样的事情:

mkdir <your directory>/repos/test

svn cat http://svn.red-bean.com/repos/test/readme.txt > <your directory>/repos/test/readme.txt

基本上,这个想法是在你想要从SVN中获取文件的目录中创建一个文件夹。 使用svn cat命令并将输出重定向到同名文件。默认情况下,cat会将信息转储到stdio。

4

Steve Jessop的回答对我没用。我查看了SVN的帮助文件,如果你只有一张图片,你可能不想再次将其检入,除非你正在使用Photoshop,因此导出是比检出更好的命令,因为它是无版本控制的(但这是小问题)。

--depth参数不应该是空的,而是文件,以获取立即目录中的文件。所以你会得到所有的字段,而不仅仅是一个,但是空的会从存储库返回nothing

 svn co --depth files <source> <local dest>

或者

svn export --depth files <source> <local dest>

至于其他答案,cat 只能读取文本内容,对于图片等其他内容不适用。


1
“--depth empty”的目的是不检出其他文件,然后您可以使用“svn up <source/file>”仅获取单个文件。使用“svn export”,无需执行此操作,只需指定文件即可。 - Kevin Vermeer
@reemrevnivek - 你是对的。问题只是要求一个单一的文件,即使它是空的,这个方法也可以工作,而不需要检出整个目录结构文件。 - Vass
你可以将svn cat的输出重定向到一个文件中。例如:svn cat svn://path/image.png >image.png - undefined

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