examinando o histórico do arquivo excluído

158

Se eu excluir um arquivo no Subversion, como posso ver seu histórico e conteúdo? Se eu tentar fazer svn catou svn logem um arquivo inexistente, ele reclama que o arquivo não existe.

Além disso, se eu quiser ressuscitar o arquivo, devo svn adddevolvê-lo?

(Perguntei especificamente sobre o Subversion, mas também gostaria de saber como Bazaar, Mercurial e Git lidam com esse caso também.)

Benjamin Peterson
fonte

Respostas:

85

Para obter o log de um arquivo excluído, use

svn log -r lastrevisionthefileexisted

Se você deseja ressuscitar o arquivo e manter seu histórico de versão, use

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

Se você quiser apenas o conteúdo do arquivo, mas não versionado (por exemplo, para uma inspeção rápida), use

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

De qualquer forma, NÃO use 'svn up' para recuperar um arquivo excluído!

Stefan
fonte
2
Você também pode ressuscitar o arquivo fazendo uma mesclagem reversa da revisão na qual você o excluiu. Este é o procedimento recomendado nos documentos do SVN. Quanto ao uso de "svn up", não se trata tanto de "não faça", mas de "não fará o que você deseja".
Rmeador 30/12/08
5
Como posso ver toda a história do arquivo?
Benjamin Peterson
71
Simples: mostre o log de uma pasta pai com a opção '-v': você receberá para cada entrada uma lista de caminhos alterados. Encontre aquele com um 'D' na frente e o nome do seu arquivo excluído. Essa é a revisão em que o arquivo foi excluído.
Stefan
7
Isso não parece funcionar para arquivos excluídos. Se eu tentar isso, recebo esta mensagem de erro: svn cat [url] /trunk/include/syeka/poster_funk.incl.php -r 50> out.txt svn: '/ admintools /! Svn / bc / 131 / trunk / caminho include / syeka / poster_funk.incl.php 'não encontrado Consulte a resposta de @Bert Huijben, mais adiante neste tópico, para uma solução em funcionamento.
Keith Palmer Jr.
2
Se eu tiver um repositório com 100.000 confirmações, "não é fácil encontrar a última versão do arquivo"!
Jon Watte 06/07/19
151

Quando você deseja olhar para arquivos antigos, realmente deve saber a diferença entre:

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

e

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

A primeira versão examina o caminho que agora está disponível como http: // server / svn / project / file e recupera esse arquivo como estava na revisão 1234. (Portanto, essa sintaxe não funciona após a exclusão de um arquivo).

A segunda sintaxe recebe o arquivo que estava disponível como http: // server / svn / project / arquivo na revisão 1234. Portanto, esta sintaxe FAZ trabalhar em arquivos excluídos.

Você pode até combinar esses métodos para recuperar um arquivo que estava disponível na revisão 2345 como http: // server / svn / project / file, mas com o conteúdo como em 1234 com:

svn cat http://server/svn/project/file@2345 -r 1234
Bert Huijben
fonte
7
Gah, obrigada! A resposta atual atual neste tópico não menciona isso, isso é ótimo!
Keith Palmer Jr.
Isso ainda falhou para mim, a menos que eu usasse caminhos absolutos, pois meu cliente svn local estava dando um erro quando não conseguia resolver ./local/filequando o ./localdiretório não existia. Isso pode não ser um problema para versões mais recentes do SVN.
Derrick Rice
2
@DerrickRice: Nesse caso, a ^notação é útil: refere-se à raiz do repositório, assim você pode dizer svn cat ^/local/file@REV(dependendo da distância entre a raiz e a URL do repositório).
Musiphil 11/09/2013
Isso funciona muito bem em princípio. Para pastas, recebo o seguinte:svn: E200009: Could not cat all targets because some targets are directories
Barney
Esta é a melhor resposta. Também tem os votos mais altos.
Felipe Alvarez
94

Primeiro, encontre o número da revisão em que o arquivo foi excluído:

svn log -v > log.txt

Em seguida, procure no log.txt (não um guru do SVN, por isso não conheço uma maneira melhor) de encontrar uma linha com

D <deleted file>

e ver qual revisão foi essa. Em seguida, como nas outras respostas, ressuscite o arquivo usando a revisão anterior.

mjy
fonte
22
svn log -v | grep D "arquivo.nome"
abatishchev 30/12/08
18
+1 por ser a primeira pessoa a responder corretamente à pergunta. Você não pode ver o conteúdo se não souber a revisão antes de ser excluída.
Cerin
8
@abatishchev obtém a lista de arquivos excluídos, mas descarta as informações da revisão, portanto não é útil. Também é lento se você estiver trabalhando com um repositório grande / antigo com muito histórico de alterações.
Tchen
4
Bom, ótimo com a melhoria de @ abatishchev. tchen: corrigido facilmente usando um argumento -B50 ou mais para grep, veja minha resposta.
Jonas Byström
2
Outra boa maneira de limitar a saída svn log -v para repositórios muito grandes / antigos é a opção -l. Então você pode usar svn log -v -l 100 | grep D "file.name"
mindmatters
27

Não é nada de especial no git. Se você souber o nome do arquivo, poderá descobrir a alteração que o removeu com o log:

git log -n 1 -- filename

Em seguida, você pode usar essa confirmação para obter o arquivo como ele existia antes da exclusão.

git checkout [last_revision]^ filename

Exemplo:

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 <[email protected]>
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

Observe que isso realmente não coloca o arquivo novamente no controle de revisão. Ele simplesmente coloca o arquivo como existia em seu estado final no local atual. Você pode adicioná-lo ou apenas inspecioná-lo ou qualquer outra coisa a partir desse ponto.

Dustin
fonte
6
Resposta maravilhosa. O único problema é que a pergunta é sobre svn!
JohnK
16

Uma solução usando apenas a GUI:

Se você souber o nome do arquivo, mas não souber o número da última revisão ou o caminho:

  1. No Repo Browser, faça um "Show log" na raiz
  2. Clique em "Mostrar tudo" (na parte inferior da caixa de diálogo do registro)
  3. Digite o nome do arquivo na caixa de texto Filtro (na parte superior da caixa de diálogo do registro)

Isso mostrará apenas as revisões em que o arquivo foi adicionado / modificado / excluído. Este é o seu histórico do arquivo.

Observe que se o arquivo foi excluído excluindo uma de suas pastas pai, ele não terá uma entrada 'excluída' no log (e, portanto, a solução de mjy não funcionará). Nesse caso, sua entrada mais recente no log filtrado corresponderá ao seu conteúdo na exclusão.

Mark Foreman
fonte
A força bruta nem sempre é a merda. Especialmente não em grandes repositórios.
Jonas Byström
+1 para uma solução exclusiva da interface do usuário. A linha de comando é ótima, e tudo, mas nem sempre é a melhor resposta sem exceção. Especialmente quando você está trabalhando em um ambiente que não controla e não tem acesso fácil à SVN na linha de comando.
Mir
Observe que a resposta acima se destina à GUI do TortoiseSVN.
Georg Muehlenberg
13
svn log -v | grep -B50 YourDeletedFileName

Você obterá o caminho e a revisão. No git (também verifica se há renomeação):

git log --diff-filter=DR --name-only | grep -B50 YourDeletedFileName
Jonas Byström
fonte
O que o -B50 faz? Posso obter uma lista de arquivos usando svn log e grep facilmente usando as dicas aqui, mas não consigo obter os números de revisão exibidos com facilidade, pois são exibidos em uma linha diferente. Eu tentei a coisa B50 e não pareceu funcionar tão incrivelmente para mim.
CEDD
Ele gera a linha matemática e as 50 linhas acima, caso alguém mais esteja lendo isso.
CEDD
8

Além da resposta de Dustin, se você quiser apenas examinar o conteúdo, e não conferir, no exemplo dele, você pode fazer:

$ git show 8d4a1f^:slosh.tac

o: separa uma revisão e um caminho nessa revisão, solicitando efetivamente um caminho específico em uma revisão específica.

Pieter
fonte
Ah, é verdade. Eu costumava fazer isso da maneira muito, muito difícil. :)
Dustin
8

Use este comando:

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

Isso listará todas as revisões que já excluíram todos os arquivos correspondentes ao padrão. Ou seja, se você estiver procurando por README arquivo, então todos /src/README, /src/README.firste /some/deeply/hidden/directory/READMENOTserá encontrado e listados.

Se o seu nome de arquivo contiver barras (caminho), pontos ou outros caracteres especiais de expressão regular, não esqueça de evitá-los para evitar incompatibilidade ou erros.

Alexander Amelkin
fonte
7

Se você não conhece o caminho para o arquivo excluído, é possível procurá -lo no svn logcomando pesado demais :

svn log --search <deleted_file_or_pattern> -v

O comando provavelmente está martelando o servidor da mesma forma que faria sem a opção de pesquisa, mas pelo menos o restante dos recursos envolvidos (incluindo seus globos oculares) seria um pouco aliviado, pois isso indicará em que revisão esse arquivo foi excluído. Em seguida, você pode seguir as outras dicas (principalmente usando o mesmo svn logcomando, mas já em um caminho definido).

JMB
fonte
svn log --search _test2.php -v... svn: opção inválida: --search ... :(
thinsoldier 26/03
5

O pôster realmente fez 3 perguntas aqui:

  1. Como eu vejo o histórico de um arquivo excluído no Subversion?
  2. Como eu vejo o conteúdo de um arquivo excluído no Subversion?
  3. Como ressuscito um arquivo excluído no Subversion?

Todas as respostas que vejo aqui são para as perguntas 2 e 3.

A resposta à pergunta 1 é:

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

Você ainda precisa obter o número da revisão para quando o arquivo existiu pela última vez, o que é claramente respondido por outras pessoas aqui.

dekeguard
fonte
4

Ah, como estou aprendendo a usar o Bazaar, é algo que tentei. Sem sucesso, parece que você não pode registrar e anotar arquivos removidos atualmente ... :-(

Tentou:

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

mas curiosamente (e felizmente) eu posso fazer:

> bzr cat -r 3 Stuff/ErrorParser.hta

e:

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

e como sugerido no bug acima:

> bzr log -v | grep -B 1 ErrorParser

(ajuste -B( --before-context) parâmetro conforme necessário).

PhiLho
fonte
1

Você precisaria especificar uma revisão.

svn log -r <revision> <deleted file>
Jack M.
fonte
1
Isso dá um erro. Exemplo: caminho svn log -r 37428 svn.example.com/deletedfile.java svn: '/!svn/bc/98571/deletedfile.java' caminho não encontrado
Jeremy
Você tem certeza de que existia nessa revisão? Você precisa especificar uma revisão onde o arquivo realmente existia.
Jack M.
Veja a resposta de Bert Huijben para ver as diferentes diferenças entre -r37428 e adicionar @ 37428 à URL do SVN.
Dubek
1

Se você deseja examinar o histórico de um arquivo antes de ser renomeado, como mencionado em um comentário aqui, você pode usar

git log --follow -- current_file_name
Andrew Grimm
fonte
1

Eu também queria uma resposta. Tente o seguinte para produzir apenas exclusões 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 } }'

Isso filtra a saída do log através do awk . O awk armazena em buffer cada linha de revisão que encontra, produzindo-a somente quando um registro de exclusão é encontrado. Cada revisão é emitida apenas uma vez, portanto, várias exclusões em uma revisão são agrupadas (como na svn logsaída padrão ).

Você pode especificar a --limitpara reduzir a quantidade de registros retornados. Você também pode remover o --stop-on-copy, conforme necessário.

Sei que há queixas sobre a eficiência de analisar todo o log. Eu acho que essa é uma solução melhor do que o grep e sua opção "lançar uma ampla rede" -B. Não sei se é mais eficiente, mas não consigo pensar em uma alternativa svn log. É semelhante à resposta de Alex Amelkin, mas não precisa de um nome específico. Também é o meu primeiro script awk , por isso pode não ser convencional.

sobrinho
fonte
1

Suponha que seu arquivo tenha sido nomeado como ~ / src / a / b / c / delete.file

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

saída de amostra, encontrada em 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

copie-o novamente para a versão anterior (90439 = 90440-1)

svn cp URL_of_deleted.file@90439 .
Daniel YC Lin
fonte
0

Você pode encontrar a última revisão que fornece o arquivo usando a pesquisa binária. Eu criei um /bin/bashscript simples para isso:

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"
}
Sebo.PL
fonte
-1

Eu escrevi um script php que copia o log svn de todos os meus repositórios em um banco de dados mysql. Agora posso fazer pesquisas de texto completo nos meus comentários ou nomes de arquivos.

mais fino
fonte