Subversion,标记文件被删除或移动后的事实

时间:2011-06-29 16:07:08

标签: svn

假设我在Subversion仓库中有两个文件:

workingcopy/
  file1.txt
  file2.txt

然后我重命名一个,在SVN外部:

$ mv file1.txt fileA.txt

现在,SVN将file1.txt标记为缺失,fileA.txt标记为未版本化

$ svn st
!   file1.txt
?   fileA.txt

就SVN而言,我删除了file1.txt并创建了一个完全不同的文件fileA.txt,因此它不会知道跟踪文件之间的变化。


编辑:这确实有效,我无法正确拼写文件名:)

同样,如果删除文件

$ rm file2.txt
$ svn st
!   file2.txt

SVN只知道文件丢失了,并且尝试将其删除标记不起作用:

$ svn remove file2.txt
svn: 'file2.txt' does not exist

我知道在Mercurial中,您可以使用--after标记将文件标记为已移动,复制,删除等,无论Mercurial在工作副本中看到什么。

SVN中有类似的技巧吗?

5 个答案:

答案 0 :(得分:12)

也许你需要更新你的Subversion版本:

$ svn --version
svn, version 1.6.16 (r1073529)

$ rm data.xml

$ svn status
!       data.xml

$ svn rm data.xml
D       data.xml

$ svn status
D       data.xml

同样的事情不能用于重命名,但编写一个执行它的shell脚本会非常容易:

#!/bin/sh

mv $2 $1
svn rename $1 $2

或者只是为了好玩,您可以将以下内容添加到.bashrc或.bash_profile:

svn_mv_after() 
{
        mv $2 $1
        svn mv $1 $2
}

alias svnmva=svn_mv_after

答案 1 :(得分:7)

如果您使用的是TortiseSVN,可以在提交屏幕上执行此操作。右键单击已删除并添加的文件(同一个文件,只需移动),您可以选择修复移动。

http://tortoisesvn.net/repairmoves.html

答案 2 :(得分:2)

没有SVN没有这样的东西,导致你通过使用操作命令“mv ..”而不是“svn mv ...”为“rm ...”离开SVN这也是同样的...... / p>

SVN跟随带有元信息“contents”的文件名,而在git,hg和bzr中,内容后面跟着元信息文件名。这就是为什么你可以使用操作系统命令重命名和删除文件,你可以用git,hg(我不知道),bzr(我也不知道)做事。

在您意识到遗漏了某些内容后,您可以做些什么......例如,如果您意外删除了某个文件:

svn revert deleted.file.ext

svn rm deleted.file.ext

在重命名文件的情况下,只有在新文件中没有更改任何内容之后才能执行此操作,之后您通过

重命名它
mv file1.txt fileA.txt

你可以做同样的事情

svn revert file1.txt

先删除fileA.txt然后再删除

svn mv file1.txt fileA.txt

如果您更改了重命名的文件(fileA.txt)中的内容,只需复制该文件并执行相同的步骤并在“svn mv ...”之后替换文件内容。

答案 3 :(得分:0)

我运行Arch Linux并在.bashrc中拥有以下内容。它可以处理您移动源的位置的新文件,并且应该能够占用大多数奇怪的路径(例如,以破折号开头或包含空格)。您需要安装realpath

svma() {
    local dst src tmp

    # Check arguments
    if [[ $# != 2 ]]; then
        echo 'Usage: svma SRC DST'
        return 1
    fi

    # Ensure paths start with a slash, not a dash
    src=$(realpath -- "$1")
    dst=$(realpath -- "$2")

    # If there is a new file at the path of the source, move it to a
    # temporary name in the same directory
    if [[ -e "$src" ]]; then
        tmp=$(mktemp "--tmpdir=$(dirname "$src")" -u)
        mv "$src" "$tmp"
    fi

    # Restore the source and then have Subversion move it
    mv "$dst" "$src"
    svn mv "$src" "$dst"

    # If required, move the new file back to the source path
    if [[ -v tmp ]]; then
        mv "$tmp" "$src"
    fi
}

答案 4 :(得分:0)

我稍微调整了@Peter Sutton的解决方案,以处理SRC缺少目录的情况,DST的目录尚未进行版本化,并采用可选的第三个参数FILE如果源文件名和目标文件名相同(如果指定了FILE,则SRCDST是目录。同样,需要realpath,我只在Cygwin中使用SVN版本1.8.11进行了测试。使用mv -b处理备份,这将删除$src~处的任何文件,并且需要手动删除由mkdir创建的任何不需要的目录。

svma() {
    local dst src tmp

    # Check arguments
    if [[ ( $# != 2 ) && ( $# != 3 ) ]]; then
        echo 'Usage: svma SRC DST [FILE]'
        return 1
    fi

    # Ensure paths start with a slash, not a dash
    src=$(realpath -- "$1")
    dst=$(realpath -- "$2")

    if [[ $# == 2 ]]; then
        srcdir=$(dirname "$src")
        dstdir=$(dirname "$dst")
    else
        srcdir="$src"
        dstdir="$dst"
        src="$srcdir/$3"
        dst="$dstdir/$3"
    fi

    mkdir -p "$srcdir"
    svn add "$dstdir" --parents --depth=empty --force

    # Restore the source and then have Subversion move it
    mv -b "$dst" "$src"
    svn mv "$src" "$dst"

    # If required, move the backed-up file back to the source path
    if [[ -e "$src~" ]]; then
        mv "$src~" "$src"
    fi
}