Tự động xóa các tệp không phiên bản Subversion


111

Có ai biết một cách để loại bỏ đệ quy tất cả các tệp trong một bản sao đang hoạt động không được kiểm soát phiên bản không? (Tôi cần điều này để có được kết quả đáng tin cậy hơn trong VMware xây dựng tự động của mình.)


7
Tôi là một người dùng SVN và đã so sánh Git với SVN để xem liệu cuối cùng tôi có muốn thực hiện chuyển đổi hay không. có vẻ như đây có thể là một ví dụ khác trong đó Git tỏa sáng với lệnh "git clean".
jpierson

3
Hoặc hg purge --allở Mercurial.
Brendan Long

Bản sao của stackoverflow.com/questions/2803823/… nơi có nhiều hoạt động hữu ích hơn.
Heath Raftery

Câu trả lời:


26

Biên tập:

Subversion 1.9.0 đã giới thiệu một tùy chọn để thực hiện việc này:

svn cleanup --remove-unversioned

Trước đó, tôi sử dụng tập lệnh python này để làm điều đó:

import os
import re

def removeall(path):
    if not os.path.isdir(path):
        os.remove(path)
        return
    files=os.listdir(path)
    for x in files:
        fullpath=os.path.join(path, x)
        if os.path.isfile(fullpath):
            os.remove(fullpath)
        elif os.path.isdir(fullpath):
            removeall(fullpath)
    os.rmdir(path)

unversionedRex = re.compile('^ ?[\?ID] *[1-9 ]*[a-zA-Z]* +(.*)')
for l in  os.popen('svn status --no-ignore -v').readlines():
    match = unversionedRex.match(l)
    if match: removeall(match.group(1))

Nó dường như làm công việc khá tốt.


1
Vẫn hoạt động với tôi với Python 2.7.2. Warren P: Bạn có thể cung cấp thêm thông tin chi tiết không?
Thomas Watnedal

Tôi nghĩ đó chỉ là một vấn đề với Python 2.6. Hoạt động lại cho tôi trong 2.7.
Warren P

1
Phản đối: Giải pháp khác từ bên dưới svn cleanup --remove-unversionedlà tốt hơn. Và nó dành cho Subversion 1.9.0 (phiên bản này có từ năm 2015). Nó ổn định và đứng vững.
tres.14159

138

điều này làm việc cho tôi trong bash:

 svn status | egrep '^\?' | cut -c8- | xargs rm

Seth Reno 's tốt hơn:

svn status | grep ^\? | cut -c9- | xargs -d \\n rm -r 

Nó xử lý các thư mục và không gian không phiên bản trong tên tệp

Theo nhận xét bên dưới, điều này chỉ hoạt động trên các tệp mà lật đổ không biết về (trạng thái =?). Bất cứ điều gì mà lật đổ không biết về (bao gồm Ignored file / folder) sẽ không bị xóa.

Nếu bạn đang sử dụng subversion 1.9 trở lên, bạn có thể chỉ cần sử dụng lệnh dọn dẹp svn với các tùy chọn --remove-unversions và --remove-bỏ qua


6
Cũng có thể sử dụng trong Windows trong cygwin.
Honza

9
Bạn có thể cân nhắc thêm tùy chọn -d vào xargs cho các tên tệp có khoảng trắng và tùy chọn -r vào rm cho bất kỳ thư mục nào được thêm vào: trạng thái svn | grep ^ \? | cắt -c9- | xargs -d \\ n rm -r
Seth Reno

4
Tôi cũng gặp sự cố với tùy chọn -d chạy trên OS X, giải pháp thay thế của tôi như sau, dịch các dấu ngắt dòng thành ký tự null và sử dụng tùy chọn -0 trên xargs để xử lý khoảng trắng trong tên tệp: trạng thái svn | grep ^ \? | cắt -c9- | tr '\ n' '\ 0' | xargs -0 rm
Brian Webster

3
Nếu bạn cau mày khi lệnh mà dựa vào chính xác số lượng ký tự trong đầu ra của lệnh khác:svn status | grep "^?" | awk '{print $2}' | xargs -d \\n rm -r
Michael Schlottke-Lakemper

3
@Pavel Hãy xem tùy chọn xargs --no-run-if-blank
Ken

71

Tôi đã lướt qua trang này trong khi tìm cách làm điều tương tự, mặc dù không phải cho một bản dựng tự động.

Sau khi xem xét kỹ hơn một chút, tôi đã phát hiện ra ' Menu ngữ cảnh mở rộng ' trong TortoiseSVN. Giữ phím shift và nhấp chuột phải vào bản sao đang làm việc. Hiện có các tùy chọn bổ sung trong menu TortoiseSVN bao gồm ' Xóa các mục chưa phiên bản ... '.

Mặc dù có lẽ không áp dụng được cho câu hỏi cụ thể này (tức là trong ngữ cảnh của một bản dựng tự động), tôi nghĩ rằng nó có thể hữu ích cho những người khác muốn làm điều tương tự.


Tuyệt quá! Trên XP, nó chỉ hoạt động ở dạng xem danh sách (bên phải của trình thám hiểm) chứ không phải ở dạng xem cây (bên trái).
Christopher Oezbek

Tuyệt vời, chỉ gửi nó vào thùng rác, sẽ rất tuyệt nếu thực hiện xóa ngay lập tức. Đúng thứ tôi cần.
Dean Thomas

Bạn cũng có thể tự động hóa việc này trên dòng lệnh với TortoiseProc.exe của TortoiseSVN: chi tiết trong câu trả lời của tôi bên dưới.
stevek_mcc 14/09/16


9

Nếu bạn đang sử dụng dòng lệnh windows,

for /f "tokens=2*" %i in ('svn status ^| find "?"') do del %i

Phiên bản cải tiến:

for /f "usebackq tokens=2*" %i in (`svn status ^| findstr /r "^\?"`) do svn delete --force "%i %j"

Nếu bạn sử dụng điều này trong một tệp hàng loạt, bạn cần phải tăng gấp đôi %:

for /f "usebackq tokens=2*" %%i in (`svn status ^| findstr /r "^\?"`) do svn delete --force "%%i %%j"

1
Loại này đã làm việc cho tôi. Có vẻ như bị nghẹt thở trên một số thư mục không phiên bản.
jpierson

7

Tôi đã thêm cái này vào hồ sơ windows powershell của mình

function svnclean {
    svn status | foreach { if($_.StartsWith("?")) { Remove-Item $_.substring(8) -Verbose } }
}

2
@FelipeAlvarez Có. Có, chúng tôi làm. Nó không phải là điều tuyệt vời nhất kể từ khi bánh mì cắt lát, nhưng nó đánh bại hàng loạt. Tôi muốn nói rằng nó ít nhất cũng hữu ích như bash, có lẽ nhiều hơn một chút vì bạn có thể kéo các hợp ngữ .NET vào.
jpmc26

Nó mắc phải xu hướng ghê tởm của microsoft đối với tính dài dòng (không chỉ về độ dài tên lệnh, mà về tổng thể là không thể hoàn thành bất cứ việc gì mà không sao chép các đoạn mã khổng lồ từ internet), nhưng nó hữu ích một cách đáng kinh ngạc và khá được suy nghĩ thấu đáo.
Warren P

1
Bạn có thể muốn thêm --no-ignorevào svn status-RecurseđểRemove-Item
Kevin Smyth

5

Dòng lệnh Linux:

svn status --no-ignore | egrep '^[?I]' | cut -c9- | xargs -d \\n rm -r

Hoặc, nếu một số tệp của bạn thuộc sở hữu của người chủ:

svn status --no-ignore | egrep '^[?I]' | cut -c9- | sudo xargs -d \\n rm -r

Điều này dựa trên câu trả lời của Ken. (Câu trả lời của Ken bỏ qua các tệp bị bỏ qua; câu trả lời của tôi sẽ xóa chúng).


5

Chỉ cần làm điều đó trên unix-shell với:

rm -rf `svn st . | grep "^?" | cut -f2-9 -d' '`

Điều này không hoạt động nếu số lượng tệp được xóa vượt quá số lượng tối đa của đối số dòng lệnh. Xem thêm các câu trả lời dựa trên xargs.
maxschlepzig

4

Bạn có thể không chỉ thực hiện xuất sang một vị trí mới và xây dựng từ đó?


1
Đối với một bản dựng tự động, tôi muốn một bản xuất sạch.
g.

1
Lý tưởng nhất là bạn nên làm điều này, nhưng điều này có vấn đề nếu thanh toán của bạn rất lớn. Đó có thể là lý do OP yêu cầu: làm cho việc xây dựng ngắn hơn.
jpmc26

4

Nếu bạn có TortoiseSVN trên đường dẫn của mình và bạn đang ở đúng thư mục:

TortoiseProc.exe /command:cleanup /path:"%CD%" /delunversioned /delignored /nodlg /noui

Các tùy chọn được mô tả trong phần trợ giúp TortoiseSVN cho /command:cleanup:

Sử dụng / noui để ngăn hộp thoại kết quả bật lên cho biết quá trình dọn dẹp đã hoàn tất hoặc hiển thị thông báo lỗi). / noprogressui cũng vô hiệu hóa hộp thoại tiến trình. / gật đầu tắt hiển thị hộp thoại dọn dẹp nơi người dùng có thể chọn chính xác những gì nên thực hiện trong quá trình dọn dẹp. Các hành động có sẵn có thể được chỉ định với các tùy chọn / dọn dẹp để dọn dẹp trạng thái, / hoàn nguyên, / xóa phiên bản, / xóa dấu, / làm mới và / bên ngoài.


4

Nếu bạn đang sử dụng rùa svn thì có một lệnh ẩn để thực hiện việc này. Giữ phím shift trong khi nhấp chuột phải vào thư mục để khởi chạy menu ngữ cảnh trong windows explorer. Bạn sẽ nhận được lệnh "Xóa các mục chưa được phiên bản".

xem chi tiết ở cuối trang này hoặc ảnh chụp màn hình bên dưới làm nổi bật các đối tượng địa lý mở rộng với các ngôi sao màu xanh lá cây và đối tượng quan tâm có hình chữ nhật màu vàng ...

Menu ngữ cảnh mở rộng SVN so với menu tiêu chuẩn



3

Chuyển đổi C # của tôi về tập lệnh Python Thomas Watnedals:

Console.WriteLine("SVN cleaning directory {0}", directory);

Directory.SetCurrentDirectory(directory);

var psi = new ProcessStartInfo("svn.exe", "status --non-interactive");
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.WorkingDirectory = directory;

using (var process = Process.Start(psi))
{
    string line = process.StandardOutput.ReadLine();
    while (line != null)
    {
        if (line.Length > 7)
        {
            if (line[0] == '?')
            {
                string relativePath = line.Substring(7);
                Console.WriteLine(relativePath);

                string path = Path.Combine(directory, relativePath);
                if (Directory.Exists(path))
                {
                    Directory.Delete(path, true);
                }
                else if (File.Exists(path))
                {
                    File.Delete(path);
                }
            }
        }
        line = process.StandardOutput.ReadLine();
    }
}

Tôi thà di chuyển các tệp chưa được phiên bản, đề phòng sau này bạn cần chúng ở đâu đó.
leppie 27/10/08

Tất nhiên, trên một máy phát triển - nhưng trong bản dựng VMware, điều đó sẽ không có ý nghĩa gì vì không ai đăng nhập vào nó và tạo tệp.
Stefan Schultze 28/10/08

Cảm ơn, tôi đã sử dụng điều này như một phần của kịch bản MSBuild tôi trong cruisecontrol để làm sạch dir nguồn của tôi trước khi xây dựng
gregmac

Bắt đầu dựa trên mã của bạn và đi một cách nữa: github.com/tgmayfield/svn-clean-sharp/downloads
Tom Mayfield

3
svn st --no-ignore  | grep '^[?I]' | sed 's/^[?I]  *//' | xargs -r -d '\n' rm -r

Đây là một lệnh unix shell để xóa tất cả các tệp không thuộc quyền kiểm soát của lật đổ.

Ghi chú:

  • các sttrong svn stlà một build-in bí danh cho status, tức là lệnh tương đương vớisvn status
  • --no-ignorecũng bao gồm các tệp không phải kho lưu trữ trong đầu ra trạng thái, nếu không sẽ bỏ qua qua các cơ chế như .cvsignorev.v. - vì mục tiêu là có một điểm khởi đầu rõ ràng cho các bản dựng, chuyển đổi này là phải
  • các grepbộ lọc đầu ra sao cho chỉ còn lại các tệp không xác định đối với bản lật ngược - các dòng bắt đầu bằng ?danh sách các tệp không xác định với bản lật ngược sẽ bị bỏ qua nếu không có --no-ignoretùy chọn
  • tiền tố lên đến tên tệp bị xóa qua sed
  • các xargslệnh được hướng dẫn qua -rđể không thực hiện rm, khi danh sách đối số sẽ được sản phẩm nào
  • các -d '\n'tùy chọn bảo xargssử dụng một dòng mới như delimiter lệnh như vậy cũng làm việc cho tên tập tin với không gian
  • rm -r được sử dụng trong trường hợp các thư mục hoàn chỉnh (không phải là một phần của kho lưu trữ) cần được xóa

2

Tôi không thể làm cho bất kỳ điều nào ở trên hoạt động mà không có phụ thuộc bổ sung mà tôi không muốn phải thêm vào hệ thống xây dựng tự động của mình trên win32. Vì vậy, tôi đã tập hợp các lệnh Ant sau đây - lưu ý rằng các lệnh này yêu cầu phải cài đặt Ant-Contrib JAR (Tôi đang sử dụng phiên bản 1.0b3, phiên bản mới nhất, với Ant 1.7.0).

Lưu ý rằng điều này sẽ xóa tất cả các tệp không phiên bản mà không có cảnh báo.

  <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
  <taskdef name="for" classname="net.sf.antcontrib.logic.ForTask" />

  <macrodef name="svnExecToProperty">
    <attribute name="params" />
    <attribute name="outputProperty" />
    <sequential>
      <echo message="Executing Subversion command:" />
      <echo message="  svn @{params}" />
      <exec executable="cmd.exe" failonerror="true"
            outputproperty="@{outputProperty}">
        <arg line="/c svn @{params}" />
      </exec>
    </sequential>
  </macrodef>

  <!-- Deletes all unversioned files without warning from the 
       basedir and all subfolders -->
  <target name="!deleteAllUnversionedFiles">
    <svnExecToProperty params="status &quot;${basedir}&quot;" 
                       outputProperty="status" />
    <echo message="Deleting any unversioned files:" />
    <for list="${status}" param="p" delimiter="&#x0a;" trim="true">
      <sequential>
        <if>
          <matches pattern="\?\s+.*" string="@{p}" />
          <then>
            <propertyregex property="f" override="true" input="@{p}" 
                           regexp="\?\s+(.*)" select="\1" />
            <delete file="${f}" failonerror="true" />
          </then>
        </if>
      </sequential>
    </for>
    <echo message="Done." />
  </target>

Đối với một thư mục khác, hãy thay đổi ${basedir}tham chiếu.


1
Lưu ý: chỉ xóa các tệp không phiên bản; không xóa các thư mục trống không phiên bản.

2
svn status --no-ignore | awk '/^[I\?]/ {system("echo rm -r " $2)}'

loại bỏ tiếng vọng nếu đó chắc chắn là điều bạn muốn làm.


1
Điều này kém hơn so với các câu trả lời dựa trên xargs vì đối với n tệp bị xóa thì có n /bin/shvà n rmquá trình được chia nhỏ.
maxschlepzig

Đã đồng ý. Cảm ơn vì thông tin xargs.
Aria

2

Vì những người khác đang làm việc đó ...

svn status | grep ^? | awk '{print $2}' | sed 's/^/.\//g' | xargs rm -R

1

Cũng có thể đóng góp một phương án khác

svn status | awk '{if($2 !~ /(config|\.ini)/ && !system("test -e \"" $2 "\"")) {print $2; system("rm -Rf \"" $2 "\"");}}'

/(Config|.ini)/ là dành cho mục đích của riêng tôi.

Và có thể là một ý tưởng hay khi thêm --no-ignore vào lệnh svn



1

Giải pháp cmd / bat cửa sổ tinh khiết:

@echo off

svn cleanup .
svn revert -R .
For /f "tokens=1,2" %%A in ('svn status --no-ignore') Do (
     If [%%A]==[?] ( Call :UniDelete %%B
     ) Else If [%%A]==[I] Call :UniDelete %%B
   )
svn update .
goto :eof

:UniDelete delete file/dir
if "%1"=="%~nx0" goto :eof
IF EXIST "%1\*" ( 
    RD /S /Q "%1"
) Else (
    If EXIST "%1" DEL /S /F /Q "%1"
)
goto :eof

Trên thực tế, tập lệnh này đã không xóa các tệp của tôi. Có thể do khoảng trống trong đó. Câu trả lời một dòng của @SukeshNambiar đã hoạt động.
Christiaan Westerbeek

1

Tôi đã thử phiên bản của Seth Reno từ câu trả lời này nhưng nó không hiệu quả với tôi. Tôi đã có 8 ký tự trước tên tệp, không phải 9 ký tự được sử dụng trong cut -c9-.

Vì vậy, đây là phiên bản của tôi với sedthay vì cut:

svn status | grep ^\? | sed -e 's/\?\s*//g' | xargs -d \\n rm -r

1

Nếu bạn thấy thú vị với powershell:

svn status --no-ignore | ?{$_.SubString(0,1).Equals("?")} | foreach { remove-item -Path (join-Path .\ $_.Replace("?","").Trim()) -WhatIf }

Lấy cờ -WhatIf ra để lệnh thực sự thực hiện việc xóa. Nếu không, nó sẽ chỉ xuất ra những gì nó sẽ làm nếu chạy mà không có -WhatIf.


1

Tôi sẽ thêm điều này làm bình luận cho câu trả lời của Thomas Watnedal , nhưng chưa thể.

Một vấn đề nhỏ với nó (sẽ không ảnh hưởng đến Windows) là nó chỉ kiểm tra các tệp hoặc thư mục. Đối với các hệ thống Unix giống như các liên kết tượng trưng có thể có, cần phải thay đổi dòng:

if os.path.isfile(fullpath):

đến

if os.path.isfile(fullpath) or os.path.islink(fullpath):

để xóa các liên kết.

Đối với tôi, thay đổi dòng cuối cùng if match: removeall(match.group(1))thành

    if match:
        print "Removing " + match.group(1)
        removeall(match.group(1))

để nó hiển thị những gì nó đang xóa cũng hữu ích.

Tùy thuộc vào trường hợp sử dụng, ?[\?ID]một phần của biểu thức chính quy có thể tốt hơn như ?[\?I], như Dcũng loại bỏ các file bị xóa, mà là dưới sự kiểm soát phiên bản. Tôi muốn sử dụng nó để xây dựng trong một thư mục đã kiểm tra, sạch sẽ, vì vậy không có tệp nào ở Dtrạng thái.


1

@zhoufei Tôi đã kiểm tra câu trả lời của bạn và đây là phiên bản cập nhật:

FOR /F "tokens=1* delims= " %%G IN ('svn st %~1 ^| findstr "^?"') DO del /s /f /q "%%H"
FOR /F "tokens=1* delims= " %%G IN ('svn st %~1 ^| findstr "^?"') DO rd /s /q "%%H"
  • Bạn phải sử dụng hai %dấu trước G và H
  • Chuyển đổi thứ tự: trước tiên hãy xóa tất cả các tệp, sau đó xóa tất cả các thư mục
  • (tùy chọn :) Thay cho %~1có thể sử dụng bất kỳ tên thư mục nào, tôi đã sử dụng tên này như một hàm trong tệp bat, thông số %~1đầu vào đầu tiên cũng vậy

0

Nếu bạn không muốn viết bất kỳ mã nào, svn2.exe từ svn2svn sẽ thực hiện điều này, cũng có một bài viết về cách nó được triển khai. Các thư mục và tệp đã xóa được bỏ vào thùng rác.

Chạy "svn2.exe sync [path]".


0

Đối với những người thích làm điều này với perl thay vì python, Unix shell, java, v.v. Đây là một tập lệnh perl nhỏ cũng thực hiện jib.

Lưu ý: Thao tác này cũng xóa tất cả các thư mục chưa được phiên bản

#!perl

use strict;

sub main()

{

    my @unversioned_list = `svn status`;

    foreach my $line (@unversioned_list)

    {

        chomp($line);

        #print "STAT: $line\n";

        if ($line =~/^\?\s*(.*)$/)

        {

            #print "Must remove $1\n";

            unlink($1);

            rmdir($1);

        }

    }

}

main();


0

Một cách rõ ràng để làm điều này trong PERL sẽ là:

#!/usr/bin/perl
use IO::CaptureOutput 'capture_exec'

my $command = sprintf ("svn status --no-ignore | grep '^?' | sed -n 's/^\?//p'");

my ( $stdout, $stderr, $success, $exit_code ) = capture_exec ( $command );
my @listOfFiles = split ( ' ', $stdout );

foreach my $file ( @listOfFiles )
{ # foreach ()
    $command = sprintf ("rm -rf %s", $file);
    ( $stdout, $stderr, $success, $exit_code ) = capture_exec ( $command );
} # foreach ()

0

Tôi đã sử dụng ~ 3 giờ để tạo ra cái này. Sẽ mất 5 phút để làm điều đó trong Unix. Vấn đề chính là: khoảng trắng trong tên cho các thư mục Win, không thể chỉnh sửa %% i và vấn đề với việc xác định các vars trong vòng lặp cmd Win.

setlocal enabledelayedexpansion

for /f "skip=1 tokens=2* delims==" %%i in ('svn status --no-ignore --xml ^| findstr /r "path"') do (
@set j=%%i
@rd /s /q !j:~0,-1!
)

0

Đoạn mã C # ở trên không hoạt động với tôi - Tôi có ứng dụng khách svn rùa và các dòng được định dạng hơi khác. Đây là đoạn mã tương tự như trên, chỉ được viết lại để hoạt động và sử dụng regex.

        /// <summary>
    /// Cleans up svn folder by removing non committed files and folders.
    /// </summary>
    void CleanSvnFolder( string folder )
    {
        Directory.SetCurrentDirectory(folder);

        var psi = new ProcessStartInfo("svn.exe", "status --non-interactive");
        psi.UseShellExecute = false;
        psi.RedirectStandardOutput = true;
        psi.WorkingDirectory = folder;
        psi.CreateNoWindow = true;

        using (var process = Process.Start(psi))
        {
            string line = process.StandardOutput.ReadLine();
            while (line != null)
            {
                var m = Regex.Match(line, "\\? +(.*)");

                if( m.Groups.Count >= 2 )
                {
                    string relativePath = m.Groups[1].ToString();

                    string path = Path.Combine(folder, relativePath);
                    if (Directory.Exists(path))
                    {
                        Directory.Delete(path, true);
                    }
                    else if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                }
                line = process.StandardOutput.ReadLine();
            }
        }
    } //CleanSvnFolder
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.