examen de l'historique du fichier supprimé


160

Si je supprime un fichier dans Subversion, comment puis-je consulter son historique et son contenu? Si j'essaye de faire svn catousvn log sur un fichier inexistant, il se plaint que le fichier n'existe pas.

De plus, si je voulais ressusciter le fichier, dois-je svn addle récupérer?

(J'ai posé une question spécifiquement sur Subversion, mais j'aimerais aussi savoir comment Bazaar, Mercurial et Git gèrent ce cas également.)

Réponses:


84

Pour obtenir le journal d'un fichier supprimé, utilisez

svn log -r lastrevisionthefileexisted

Si vous souhaitez ressusciter le fichier et conserver son historique des versions, utilisez

svn copy url/of/file@lastrevisionthefileexisted -r lastrevisionthefileexisted path/to/workingcopy/file

Si vous voulez simplement que le contenu du fichier ne soit pas versionné (par exemple, pour une inspection rapide), utilisez

svn cat url/of/file@lastrevisionthefileexisted -r latrevisionthefileexisted > file

Dans tous les cas, n'utilisez PAS 'svn up' pour récupérer un fichier supprimé!


2
Vous pouvez également ressusciter le fichier en effectuant une fusion inversée de la révision dans laquelle vous l'avez supprimé. C'est la procédure recommandée dans la documentation SVN. Quant à l'utilisation de "svn up", ce n'est pas tant une question de "ne pas le faire" que de "il ne fera pas ce que vous voulez qu'il fasse".
rmeador

5
Comment puis-je voir l'historique complet du fichier?
Benjamin Peterson

71
Simple: affichez le journal d'un dossier parent avec le commutateur '-v': vous obtiendrez pour chaque entrée une liste des chemins modifiés. Trouvez celui avec un «D» devant et le nom de votre fichier supprimé. C'est la révision où le fichier a été supprimé.
Stefan

8
Cela ne semble pas fonctionner pour les fichiers supprimés. Si j'essaye ceci, j'obtiens ce message d'erreur: svn cat [url] /trunk/include/syeka/poster_funk.incl.php -r 50> out.txt svn: '/ admintools /! Svn / bc / 131 / trunk / include / syeka / poster_funk.incl.php 'chemin non trouvé Voir la réponse de @Bert Huijben plus loin dans ce fil pour une solution de travail.
Keith Palmer Jr.

2
Si j'ai un repo avec 100 000 commits, "lastrevisionthefileexisted" n'est pas facile à trouver!
Jon Watte

151

Lorsque vous souhaitez consulter d'anciens fichiers, vous devez vraiment connaître la différence entre:

svn cat http://server/svn/project/file -r 1234

et

svn cat http://server/svn/project/file@1234

La première version examine le chemin qui est maintenant disponible en tant que http: // serveur / svn / project / file et récupère ce fichier tel qu'il était dans la révision 1234. (Cette syntaxe ne fonctionne donc pas après une suppression de fichier).

La seconde syntaxe obtient le fichier qui était disponible http: // serveur / svn / projet / fichier dans la révision 1234. Donc cette syntaxe DOES travail sur les fichiers supprimés.

Vous pouvez même combiner ces méthodes pour récupérer un fichier qui était disponible dans la révision 2345 en tant que http: // server / svn / project / file mais avec le contenu comme il l'avait en 1234 avec:

svn cat http://server/svn/project/file@2345 -r 1234

7
Gah, merci! La meilleure réponse actuelle dans ce fil ne mentionne pas cela, c'est génial!
Keith Palmer Jr.

Cela a toujours échoué pour moi à moins d'utiliser des chemins absolus, car mon client svn local donnait une erreur lorsqu'il était incapable de résoudre ./local/filelorsque le ./localrépertoire n'existait pas. Cela peut ne pas être un problème pour les versions plus récentes de SVN.
Derrick Rice le

2
@DerrickRice: Dans ce cas, la ^notation est pratique: elle fait référence à la racine du référentiel, donc vous pouvez dire svn cat ^/local/file@REV(en fonction de la distance entre la racine du référentiel et l'URL).
musiphil

Cela fonctionne très bien en principe. Pour les dossiers, je reçois ce qui suit:svn: E200009: Could not cat all targets because some targets are directories
Barney

C'est la meilleure réponse. A aussi les votes les plus élevés.
Felipe Alvarez

94

Tout d'abord, recherchez le numéro de révision où le fichier a été supprimé:

svn log -v > log.txt

Ensuite, regardez dans log.txt (pas un gourou SVN, donc je ne connais pas de meilleur moyen) pour une ligne avec

D <deleted file>

et voyez quelle révision c'était. Puis, comme dans les autres réponses, ressuscitez le fichier en utilisant la révision précédente.


22
svn log -v | grep D "file.name"
abatishchev

18
+1 pour avoir été la première personne à répondre correctement à la question. Vous ne pouvez pas consulter le contenu si vous ne connaissez pas la révision avant sa suppression.
Cerin

8
@abatishchev cela obtient la liste des fichiers supprimés, mais rejette les informations de révision, donc ce n'est pas utile. De plus, c'est lent si vous travaillez avec un grand / ancien référentiel avec beaucoup d'historique des modifications.
tchen

4
Bien, très bien avec l'amélioration de @ abatishchev. tchen: facilement corrigé en utilisant un argument -B50 ou plus de grep, voir ma réponse.
Jonas Byström

2
Un autre bon moyen de limiter la sortie svn log -v pour les référentiels très volumineux / anciens est l'option -l. Vous pouvez donc utiliser svn log -v -l 100 | grep D "file.name"
mindmatters

27

Ce n'est rien de particulièrement spécial dans git. Si vous connaissez le nom du fichier, vous pouvez découvrir le changement qui l'a supprimé avec le journal:

git log -n 1 -- filename

Ensuite, vous pouvez utiliser cette validation pour obtenir le fichier tel qu'il existait avant la suppression.

git checkout [last_revision]^ filename

Exemple:

dhcp-120:/tmp/slosh 587% ls -l slosh.tac
ls: slosh.tac: No such file or directory
dhcp-120:/tmp/slosh 588% git log -n 1 -- slosh.tac
commit 8d4a1f1a94e4aa37c1cb9d329a140d08eec1b587
Author: Dustin Sallings <dustin@spy.net>
Date:   Mon Dec 15 11:25:00 2008 -0800

    Get rid of a .conf and replace it with .tac.
dhcp-120:/tmp/slosh 589% git checkout 8d4a1f^ slosh.tac
dhcp-120:/tmp/slosh 590% ll slosh.tac
-rw-------  1 dustin  wheel  822 Dec 30 12:52 slosh.tac

Notez que cela ne remet pas réellement le fichier dans le contrôle de révision. Il dépose simplement le fichier tel qu'il existait dans son état final dans l'emplacement actuel. Vous pouvez ensuite l'ajouter ou simplement l'inspecter ou quoi que ce soit à partir de ce point.


6
Merveilleuse réponse. Le seul problème est que la question concerne svn!
JohnK

16

Une solution utilisant uniquement l'interface graphique:

Si vous connaissez le nom du fichier, mais que vous ne connaissez pas son dernier numéro de révision ni même son chemin:

  1. Depuis le navigateur Repo, faites un "Afficher le journal" à la racine
  2. Cliquez sur "Afficher tout" (au bas de la boîte de dialogue du journal)
  3. Tapez le nom du fichier dans la zone de texte Filtre (en haut de la boîte de dialogue du journal)

Cela affichera alors uniquement les révisions où le fichier a été ajouté / modifié / supprimé. Ceci est votre historique du fichier.

Notez que si le fichier a été supprimé en supprimant l'un de ses dossiers parents, il n'aura pas d'entrée «supprimé» dans le journal (et donc la solution de mjy ne fonctionnera pas). Dans ce cas, son entrée la plus récente dans le journal filtré correspondra à son contenu lors de la suppression.


La force brute n'est pas toujours la merde. Surtout pas sur les gros repos.
Jonas Byström

+1 pour une solution UI uniquement. La ligne de commande est excellente, et tout, mais ce n'est pas toujours la meilleure réponse sans exception. Surtout lorsque vous travaillez dans un environnement que vous ne contrôlez pas et que vous ne disposez pas d'un accès facile en ligne de commande à SVN.
Mir

Veuillez noter que la réponse ci-dessus est destinée à l'interface graphique de TortoiseSVN.
Georg Muehlenberg

13
svn log -v | grep -B50 YourDeletedFileName

Vous obtiendrez le chemin et la révision. Dans git (vérifie également les renommés):

git log --diff-filter=DR --name-only | grep -B50 YourDeletedFileName

Que fait le -B50? Je peux obtenir une liste de fichiers en utilisant svn log et grep assez facilement en utilisant les astuces ici, mais je ne parviens pas à afficher facilement les numéros de révision, étant donné qu'ils sont affichés sur une ligne différente. J'ai essayé le truc B50 et cela ne semblait pas fonctionner à merveille pour moi.
cedd le

Il sort la ligne mathématique et les 50 lignes au-dessus au cas où quelqu'un d'autre lirait ceci.
cedd le

8

En plus de la réponse de Dustin, si vous voulez juste examiner le contenu, et non le vérifier, dans son exemple, vous pouvez faire:

$ git show 8d4a1f^:slosh.tac

the: sépare une révision et un chemin dans cette révision, demandant effectivement un chemin spécifique à une révision spécifique.


Ah, très vrai. J'avais l'habitude de faire ça de manière vraiment très difficile. :)
Dustin

8

Utilisez cette commande:

svn log -v | awk '/^r[0-9]+/ { rev = $1; }; / D .*filename_escaped_for_regex/ { print rev" "$2; };'

Cela listera toutes les révisions qui ont supprimé tous les fichiers correspondant au modèle. C'est, si vous êtes à la recherche de fichier README, puis tous /src/README, /src/README.firstet /some/deeply/hidden/directory/READMENOTseront trouvés et répertoriés.

Si votre nom de fichier contient des barres obliques (chemin), des points ou d'autres caractères spéciaux de regex, n'oubliez pas de les échapper pour éviter les incohérences ou les erreurs.


7

Si vous ne connaissez pas le chemin d'accès au fichier supprimé, il s'avère que vous pouvez le rechercher dans la commande autrement trop lourde svn log:

svn log --search <deleted_file_or_pattern> -v

La commande martèle probablement le serveur autant qu'elle le ferait sans l'option de recherche, mais au moins le reste des ressources impliquées (y compris vos globes oculaires) serait un peu soulagé, car cela vous dira dans quelle révision ce fichier a été supprimé. Ensuite, vous pouvez suivre les autres astuces (principalement en utilisant la même svn logcommande, mais déjà sur un chemin défini).


svn log --search _test2.php -v... svn: option invalide: --search ... :(
thinsoldier

5

L'affiche a en fait posé 3 questions ici:

  1. Comment consulter l'historique d'un fichier supprimé dans Subversion?
  2. Comment consulter le contenu d'un fichier supprimé dans Subversion?
  3. Comment ressusciter un fichier supprimé dans Subversion?

Toutes les réponses que je vois ici concernent les questions 2 et 3.

La réponse à la question 1 est:

svn log http://server/svn/project/file@1234

Vous devez toujours obtenir le numéro de révision de la date à laquelle le fichier a existé pour la dernière fois, qui est clairement répondu par d'autres ici.


4

Ah, depuis que j'apprends à utiliser Bazaar, c'est quelque chose que j'ai essayé. Sans succès, il semble que vous ne pouvez pas enregistrer et annoter les fichiers supprimés actuellement ... :-(

A essayé:

> bzr log -r 3 Stuff/ErrorParser.hta
bzr: ERROR: Path does not have any revision history: Stuff/ErrorParser.hta

mais curieusement (et heureusement) je peux faire:

> bzr cat -r 3 Stuff/ErrorParser.hta

et:

> bzr diff -r 2..3 Stuff/ErrorParser.hta

et comme suggéré dans le bogue ci-dessus:

> bzr log -v | grep -B 1 ErrorParser

(ajustez le paramètre -B( --before-context) si nécessaire).


1

Vous devrez spécifier une révision.

svn log -r <revision> <deleted file>

1
Cela donne une erreur. Exemple: svn log -r 37428 svn.example.com/deletedfile.java svn: '/!svn/bc/98571/deletedfile.java' chemin non trouvé
Jeremy

Êtes-vous sûr qu'il existait à cette révision? Vous devez spécifier une révision là où le fichier existait réellement.
Jack M.

Voir la réponse de Bert Huijben pour la différence étrange entre -r37428 et l'ajout de @ 37428 à l'URL SVN.
dubek

1

Si vous souhaitez consulter l'historique d'un fichier avant qu'il ne soit renommé, comme mentionné dans un commentaire ici, vous pouvez utiliser

git log --follow -- current_file_name

1

Je voulais une réponse, moi-même. Essayez ce qui suit pour ne sortir que les suppressions de svn log.

svn log --stop-on-copy --verbose [--limit <limit>] <repo Url> | \
awk '{ if ($0 ~ /^r[0-9]+/) rev = $0 }
  { if ($0 ~ /^ D /) { if (rev != "") { print rev; rev = "" }; print $0 } }'

Cela filtre la sortie du journal via awk . awk met en mémoire tampon chaque ligne de révision qu'il trouve, ne la sortant que lorsqu'un enregistrement de suppression est trouvé. Chaque révision n'est sortie qu'une seule fois, donc plusieurs suppressions dans une révision sont regroupées (comme dans la normesvn log sortie ).

Vous pouvez spécifier a --limitpour réduire le nombre d'enregistrements renvoyés. Vous pouvez également supprimer le--stop-on-copy , si nécessaire.

Je sais qu'il y a des plaintes concernant l'efficacité de l'analyse de l'ensemble du journal. Je pense que c'est une meilleure solution que grep et son -Boption "cast a wide net" . Je ne sais pas si c'est plus efficace, mais je ne peux pas penser à une alternative svn log. C'est similaire à la réponse de @Alexander Amelkin, mais n'a pas besoin d'un nom spécifique. C'est aussi mon premier script awk , donc ce n'est peut-être pas conventionnel.


1

Supposons que votre fichier a été nommé comme ~ / src / a / b / c / supprimé.fichier

cd ~/src/a/b/c  # to the directory where you do the svn rm or svn mv command
#cd ~/src   # if you forget the correct directory, just to the root of repository
svn log -v | grep -w -B 9 deleted.file | head  # head show first 10 lines

exemple de sortie, trouvé à r90440

...
r90440 | user | 2017-02-03 11:55:09 +0800 (Fri, 03 Feb 2017) | 4 lines
Changed paths:
  M /src/a/b/c/foo
  M /src/a/b/c/bar
  D /src/a/b/c/deleted.file

recopiez-le vers la version précédente (90439 = 90440-1)

svn cp URL_of_deleted.file@90439 .

0

Vous pouvez trouver la dernière révision qui fournit le fichier en utilisant la recherche binaire. J'ai créé un /bin/bashscript simple pour cela:

function svnFindLast(){
 # The URL of the file to be found
 local URL="$1"
 # The SVN revision number which the file appears in (any rev where the file DOES exist)
 local r="$2"
 local R
 for i in $(seq 1 "${#URL}")
  do
   echo "checkingURL:'${URL:0:$i}'" >&2
   R="$(svn info --show-item revision "${URL:0:$i}" 2>/dev/null)"
   echo "R=$R" >&2
   [ -z "$R" ] || break
 done
 [ "$R" ] || {
  echo "It seems '$URL' is not in a valid SVN repository!" >&2
  return -1
 }
 while [ "$r" -ne "$R" -a "$(($r + 1))" -ne "$R" ]
 do
  T="$(($(($R + $r)) / 2))"
  if svn log "${URL}@${T}" >/dev/null 2>&1
   then
    r="$T"
    echo "r=$r" >&2
   else
    R="$T"
    echo "R=$R" >&2
  fi
 done
 echo "$r"
}

-1

J'ai écrit un script php qui copie le journal svn de tous mes référentiels dans une base de données mysql. Je peux maintenant faire des recherches en texte intégral sur mes commentaires ou noms de fichiers.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.