Entfernen Sie nicht konvertierte Subversion-Dateien automatisch


111

Kennt jemand eine Möglichkeit, alle Dateien in einer Arbeitskopie, die nicht der Versionskontrolle unterliegen, rekursiv zu entfernen? (Ich benötige dies, um zuverlässigere Ergebnisse in meiner automatisch erstellten VMware zu erzielen.)


7
Ich bin ein SVN-Benutzer und habe Git mit SVN verglichen, um zu sehen, ob ich irgendwann den Wechsel vornehmen möchte. es sieht so aus, als wäre dies ein weiteres Beispiel, bei dem Git mit seinem Befehl "git clean" glänzt.
Jpierson

3
Oder hg purge --allin Mercurial.
Brendan Long

Duplikat von stackoverflow.com/questions/2803823/…, wo es viel mehr nützliche Aktivitäten gibt.
Heath Raftery

Antworten:


26

Bearbeiten:

Subversion 1.9.0 führte eine Option ein, um dies zu tun:

svn cleanup --remove-unversioned

Vorher benutze ich dieses Python-Skript, um das zu tun:

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))

Es scheint den Job ziemlich gut zu machen.


1
Funktioniert immer noch für mich mit Python 2.7.2. Warren P: Können Sie weitere Details bereitstellen?
Thomas Watnedal

Ich denke, es war nur ein Problem mit Python 2.6. Funktioniert wieder für mich in 2.7.
Warren P

1
Downvote: Die andere Lösung von unten svn cleanup --remove-unversionedist besser. Und es ist für Subversion 1.9.0 (diese Version ist von 2015). Es ist stabil und standardisiert.
tres.14159

138

das funktioniert bei mir in bash:

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

Seth Renos ist besser:

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

Es behandelt nicht versionierte Ordner und Leerzeichen in Dateinamen

Wie in den Kommentaren unten angegeben, funktioniert dies nur bei Dateien, von denen Subversion nichts weiß (status =?). Alles , was Subversion nicht kennen (einschließlich Ignoriert Dateien / Ordner) werden nicht gelöscht.

Wenn Sie Subversion 1.9 oder höher verwenden, können Sie einfach den Befehl svn cleanup mit den Optionen --remove-unversioned und --remove-ignore verwenden


6
Auch in Windows in Cygwin verwendbar.
Honza

9
Sie können die Option -d zu xargs für Dateinamen mit Leerzeichen und die Option -r zu rm für hinzugefügte Verzeichnisse hinzufügen: svn status | grep ^ \? | cut -c9- | xargs -d \\ n rm -r
Seth Reno

4
Ich hatte auch Probleme mit der Option -d, die unter OS X ausgeführt wird. Meine Alternative lautet wie folgt: Die Zeilenumbrüche werden in Nullzeichen übersetzt und die Option -0 für xargs verwendet, um Leerzeichen in Dateinamen zu verarbeiten: svn status | grep ^ \? | cut -c9- | tr '\ n' '\ 0' | xargs -0 rm
Brian Webster

3
Wenn Sie Befehle svn status | grep "^?" | awk '{print $2}' | xargs -d \\n rm -r
missbilligen

3
@ Pavel Werfen Sie einen Blick auf die Option xargs --no-run-if-empty
Ken

71

Ich bin auf diese Seite gestoßen, als ich versucht habe, dasselbe zu tun, allerdings nicht für einen automatisierten Build.

Nach einigem Hin und Her entdeckte ich das ' Extended Context Menu ' in TortoiseSVN. Halten Sie die Umschalttaste gedrückt und klicken Sie mit der rechten Maustaste auf die Arbeitskopie. Es gibt jetzt zusätzliche Optionen im TortoiseSVN-Menü, einschließlich " Nicht versionierte Elemente löschen ... ".

Obwohl dies für diese spezielle Frage möglicherweise nicht zutreffend ist (dh im Kontext eines automatisierten Builds), dachte ich, dass es für andere hilfreich sein könnte, die das Gleiche tun möchten.


Toll! Unter XP funktioniert es nur in der Listenansicht (rechte Seite des Explorers), nicht in der Baumansicht (linke Seite).
Christopher Oezbek

Fantastisch, nur in den Papierkorb schicken, wäre schön, einen direkten Löschvorgang durchzuführen. Genau das, was ich brauchte.
Dean Thomas

Sie können dies auch in der Befehlszeile mit TortoiseSVNs TortoiseProc.exe automatisieren: Details in meiner Antwort unten.
stevek_mcc


9

Wenn Sie sich in der Windows-Befehlszeile befinden,

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

Verbesserte Version:

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

Wenn Sie dies in einer Batch-Datei verwenden, müssen Sie Folgendes verdoppeln %:

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

1
Das hat irgendwie für mich funktioniert. Schien jedoch an einigen nicht umgesetzten Ordnern zu ersticken.
Jpierson

7

Ich habe dies meinem Windows-Powershell-Profil hinzugefügt

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

2
@FelipeAlvarez Ja. Ja, machen wir. Es ist nicht das Beste seit geschnittenem Brot, aber es schlägt Batch. Ich würde sagen, es ist mindestens so nützlich wie Bash, wahrscheinlich ein bisschen mehr, da Sie .NET-Assemblys einlesen können.
jpmc26

Es leidet unter der abscheulichen Tendenz von Microsoft zur Ausführlichkeit (nicht nur in Bezug auf die Länge des Befehlsnamens, sondern auch in der Unmöglichkeit, etwas zu erledigen, ohne riesige Ausschnitte aus dem Internet zu kopieren), aber es ist schockierend nützlich und ziemlich gut durchdacht.
Warren P

1
Sie können hinzufügen möchten --no-ignoreauf svn statusund -RecursezuRemove-Item
Kevin Smyth

5

Linux-Befehlszeile:

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

Oder wenn einige Ihrer Dateien root gehören:

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

Dies basiert auf Kens Antwort. (Kens Antwort überspringt ignorierte Dateien; meine Antwort löscht sie).


5

Mach es einfach auf Unix-Shell mit:

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

Dies funktioniert nicht, wenn die Anzahl der zu löschenden Dateien die maximale Anzahl der Befehlszeilenargumente überschreitet. Siehe auch die xargs-basierten Antworten.
Maxschlepzig

4

Können Sie nicht einfach einen Export an einen neuen Standort durchführen und von dort aus bauen?


1
Für einen automatisierten Build würde ich einen sauberen Export wünschen.
g.

1
Idealerweise würden Sie dies tun, aber dies ist problematisch, wenn Ihre Kasse sehr groß ist. Dies ist wahrscheinlich der Grund, warum das OP gefragt hat: den Build zu verkürzen.
jpmc26

4

Wenn Sie TortoiseSVN auf Ihrem Weg haben und sich im richtigen Verzeichnis befinden:

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

Die Optionen sind in der TortoiseSVN-Hilfe beschrieben für /command:cleanup:

Verwenden Sie / noui, um zu verhindern, dass der Ergebnisdialog angezeigt wird, der entweder über den Abschluss der Bereinigung informiert oder eine Fehlermeldung anzeigt. / noprogressui deaktiviert auch den Fortschrittsdialog. / nodlg deaktiviert die Anzeige des Bereinigungsdialogs, in dem der Benutzer auswählen kann, was genau bei der Bereinigung getan werden soll. Die verfügbaren Aktionen können mit den Optionen / cleanup für Statusbereinigung, / revert, / delunversioned, / delignored, / refreshshell und / externals angegeben werden.


4

Wenn Sie tortoise svn verwenden, gibt es einen versteckten Befehl, um dies zu tun. Halten Sie die Umschalttaste gedrückt, während Sie mit der rechten Maustaste auf einen Ordner klicken, um das Kontextmenü im Windows Explorer zu starten. Sie erhalten den Befehl "Nicht versionierte Elemente löschen".

Weitere Informationen finden Sie unten auf dieser Seite oder in der Abbildung unten, in der die erweiterten Funktionen mit den grünen Sternen und die mit dem gelben Rechteck von Interesse hervorgehoben werden.

SVN Erweitertes Kontextmenü im Vergleich zum Standardmenü



3

Meine C # -Konvertierung von Thomas Watnedals Python-Skript:

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();
    }
}

Ich würde die nicht versionierten Dateien lieber verschieben, nur für den Fall, dass Sie sie später irgendwo brauchen.
Leppie

Natürlich auf einem Entwicklungscomputer - aber in der Build-VMware macht das keinen Sinn, da sich niemand anmeldet und Dateien erstellt.
Stefan Schultze

Vielen Dank, ich habe dies als Teil meines MSBuild-Skripts in Cruisecontrol verwendet, um mein Quellverzeichnis vor dem Erstellen zu bereinigen
Gregmac

Begonnen basierend auf Ihrem Code und ging noch einen Schritt weiter: 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

Dies ist ein Unix-Shell-Befehl zum Löschen aller Dateien, die nicht unter Subversionskontrolle stehen.

Anmerkungen:

  • Das stIn svn stist ein eingebauter Alias ​​für status, dh der Befehl entsprichtsvn status
  • --no-ignoreEnthält auch Nicht-Repository-Dateien in der Statusausgabe, die ansonsten über Mechanismen wie .cvsignoreusw. ignoriert werden . Da das Ziel darin besteht, einen sauberen Ausgangspunkt für Builds zu haben, ist dieser Schalter ein Muss
  • Die grepFilter filtern die Ausgabe so, dass nur Dateien übrig bleiben, die der Subversion unbekannt sind. Die Zeilen, die mit ?Listendateien beginnen, die der Subversion unbekannt sind, werden ohne die --no-ignoreOption ignoriert
  • Das Präfix bis zum Dateinamen wird über entfernt sed
  • Der xargsBefehl wird angewiesen -r, nicht auszuführen rm, wenn die Argumentliste leer wäre
  • Die -d '\n'Option weist xargsan, einen Zeilenumbruch als Trennzeichen zu verwenden, sodass der Befehl auch für Dateinamen mit Leerzeichen funktioniert
  • rm -r wird verwendet, wenn vollständige Verzeichnisse (die nicht Teil des Repositorys sind) entfernt werden müssen

2

Ohne zusätzliche Abhängigkeiten, die ich meinem automatisierten Build-System unter win32 nicht hinzufügen wollte, konnte ich keines der oben genannten Verfahren zum Laufen bringen. Daher habe ich die folgenden Ant-Befehle zusammengestellt. Beachten Sie, dass für diese die Ant-Contrib-JAR installiert sein muss (ich habe die neueste Version 1.0b3 mit Ant 1.7.0 verwendet).

Beachten Sie, dass dadurch alle nicht konvertierten Dateien ohne Warnung gelöscht werden.

  <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>

Ändern Sie für einen anderen Ordner die ${basedir}Referenz.


1
Hinweis: Löscht nur nicht versionierte Dateien. entfernt keine leeren nicht versionierten Ordner.

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

Entfernen Sie das Echo, wenn Sie sicher sind, was Sie tun möchten.


1
Dies ist den xargs-basierten Antworten unterlegen, da für n zu löschende Dateien n /bin/shund n rmProzesse gegabelt sind.
Maxschlepzig

Einverstanden. Danke für die xargs Infos.
Aria

2

Da alle anderen es tun ...

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

1

Könnte auch eine andere Option beitragen

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

Die /(config|.ini)/ ist für meine eigenen Zwecke.

Und möglicherweise ist es eine gute Idee, dem Befehl svn --no-ignore hinzuzufügen



1

Reine Windows cmd / bat Lösung:

@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

Eigentlich hat dieses Skript meine Dateien nicht gelöscht. Möglicherweise aufgrund von Leerzeichen. Die einzeilige Antwort von @SukeshNambiar hat funktioniert.
Christiaan Westerbeek

1

Ich habe Seth Renos Version anhand dieser Antwort ausprobiert , aber es hat bei mir nicht funktioniert. Ich hatte 8 Zeichen vor dem Dateinamen, nicht 9 in cut -c9-.

Das ist also meine Version mit sedanstelle von cut:

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

1

Wenn du cool mit Powershell bist:

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

Entfernen Sie das Flag -WhatIf, damit der Befehl die Löschvorgänge tatsächlich ausführt. Andernfalls wird nur ausgegeben, was es tun würde , wenn es ohne -WhatIf ausgeführt würde.


1

Ich würde dies als Kommentar zu Thomas Watnedals Antwort hinzufügen , kann es aber noch nicht.

Ein kleines Problem (das Windows nicht betrifft) ist, dass nur nach Dateien oder Verzeichnissen gesucht wird. Bei Unix-ähnlichen Systemen, in denen möglicherweise symbolische Verknüpfungen vorhanden sind, muss die Zeile geändert werden:

if os.path.isfile(fullpath):

zu

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

um auch Links zu entfernen.

Für mich die letzte Zeile if match: removeall(match.group(1))in ändern

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

Es war auch nützlich, um anzuzeigen, was entfernt wird.

Je nach Anwendungsfall kann der ?[\?ID]Teil des regulären Ausdrucks besser sein ?[\?I], da Dauch gelöschte Dateien entfernt werden, die unter Versionskontrolle standen. Ich möchte dies verwenden, um einen sauberen, eingecheckten Ordner zu erstellen, sodass sich keine Dateien in einem DStatus befinden sollten .


1

@zhoufei Ich habe deine Antwort getestet und hier ist die aktualisierte Version:

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"
  • Sie müssen zwei %Markierungen vor G und H verwenden
  • Ändern Sie die Reihenfolge: Entfernen Sie zuerst alle Dateien und dann alle Verzeichnisse
  • (optional :) Anstelle von %~1kann jeder Verzeichnisname verwendet werden, ich habe dies als Funktion in einer Bat-Datei verwendet, also %~1ist erster Eingabeparameter

0

Wenn Sie keinen Code schreiben möchten, führt svn2.exe von svn2svn dies aus. Außerdem gibt es einen Artikel über die Implementierung. Gelöschte Ordner und Dateien werden in den Papierkorb gelegt.

Führen Sie "svn2.exe sync [path]" aus.


0

Für die Leute, die dies gerne mit Perl anstelle von Python, Unix-Shell, Java usw. machen. Hiermit ein kleines Perl-Skript, das auch den Fock macht.

Hinweis: Dadurch werden auch alle nicht konvertierten Verzeichnisse entfernt

#!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

Ein sauberer Weg, dies in PERL zu tun, wäre:

#!/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

Ich habe ~ 3 Stunden gebraucht, um dies zu generieren. Unter Unix würde dies 5 Minuten dauern. Das Hauptproblem war: Leerzeichen in Namen für Win-Ordner, Unmöglichkeit, %% i zu bearbeiten, und Problem beim Definieren von Variablen in der Win-Cmd-Schleife.

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

Das obige C # -Code-Snipet hat bei mir nicht funktioniert - ich habe einen Schildkröten-SVN-Client und die Zeilen sind etwas anders formatiert. Hier ist das gleiche Code-Snipet wie oben, nur umgeschrieben, um zu funktionieren und Regex zu verwenden.

        /// <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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.