Étant donné le hachage d'un blob, existe-t-il un moyen d'obtenir une liste des validations qui ont ce blob dans leur arborescence?
git
version-control
Lecture seulement
la source
la source
git hash-object
ousha1("blob " + filesize + "\0" + data)
, et pas simplement le sha1sum du contenu de l'objet blob.git log --follow filepath
(et l'utiliser pour accélérer la solution d'Aristote, si vous le souhaitez).~/.bin
et nommez-legit-find-object
. Vous pouvez ensuite l'utiliser avecgit find-object
.git describe <hash>
: voir ma réponse ci-dessous .Réponses:
Les deux scripts suivants prennent le SHA1 de l'objet blob comme premier argument, et après, éventuellement, tous les arguments qui
git log
comprendront. Par exemple,--all
pour rechercher dans toutes les branches au lieu de la seule en cours, ou-g
pour rechercher dans le reflog, ou tout ce que vous voulez.Ici, c'est comme un script shell - court et doux, mais lent:
Et une version optimisée en Perl, encore assez courte mais beaucoup plus rapide:
la source
git rev-parse --verify $theprefix
my $blob_arg = shift; open my $rev_parse, '-|', git => 'rev-parse' => '--verify', $blob_arg or die "Couldn't open pipe to git-rev-parse: $!\n"; my $obj_name = <$rev_parse>; chomp $obj_name; close $rev_parse or die "Couldn't expand passed blob.\n"; $obj_name eq $blob_arg or print "(full blob is $obj_name)\n";
obj_name="$1" shift git log --all --pretty=format:'%T %h %s %n' -- "$@" | while read tree commit cdate subject ; do if [ -z $tree ] ; then continue fi if git ls-tree -r $tree | grep -q "$obj_name" ; then echo "$cdate $commit $@ $subject" fi done
--all
comme argument supplémentaire. (Il est important de trouver tous les commits à l'échelle du dépôt dans des cas comme la suppression d'un gros fichier de l'historique du dépôt ).Malheureusement, les scripts étaient un peu lents pour moi, j'ai donc dû optimiser un peu. Heureusement, j'avais non seulement le hachage mais aussi le chemin d'un fichier.
la source
<hash>
at the donné<path>
, alors la suppression de l'<path>
argument de lagit log
fonctionnera. Le premier résultat renvoyé est le commit voulu.Avec Git 2.16 (Q1 2018), ce
git describe
serait une bonne solution, car il a été appris à creuser des arbres plus profondément pour trouver un<commit-ish>:<path>
qui fait référence à un objet blob donné.Voir commit 644eb60 , commit 4dbc59a , commit cdaed0c , commit c87b653 , commit ce5b6f9 (16 novembre 2017) et commit 91904f5 , commit 2deda00 (02 novembre 2017) par Stefan Beller (
stefanbeller
) .(Fusionné par Junio C Hamano -
gitster
- in commit 556de1a , 28 déc 2017)Cela signifie que la
git describe
page de manuel ajoute aux objectifs de cette commande:Mais:
la source
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | awk '/^blob/ {print substr($0,6)}' | sort --numeric-sort --key=2 -r | head -n 20
, qui vous renvoie un top 20 des plus gros blobs. Ensuite, vous pouvez transmettre l'ID de l'objet blob de la sortie ci-dessus àgit describe
. A travaillé comme un charme! Merci!Je pensais que ce serait une chose généralement utile à avoir, alors j'ai écrit un petit script perl pour le faire:
Je mettrai ça sur github quand je rentrerai à la maison ce soir.
Mise à jour: il semble que quelqu'un l'ait déjà fait . Celui-ci utilise la même idée générale mais les détails sont différents et la mise en œuvre est beaucoup plus courte. Je ne sais pas ce qui serait le plus rapide mais les performances ne sont probablement pas un problème ici!
Mise à jour 2: Pour ce que ça vaut, ma mise en œuvre est beaucoup plus rapide, en particulier pour un grand référentiel. Cela
git ls-tree -r
fait vraiment mal.Mise à jour 3: Je dois noter que mes commentaires sur les performances ci-dessus s'appliquent à l'implémentation que j'ai liée ci-dessus dans la première mise à jour. L'implémentation d'Aristote est comparable à la mienne. Plus de détails dans les commentaires pour ceux qui sont curieux.
la source
git rev-parse $commit^{}
Bien que la question d'origine ne le demande pas, je pense qu'il est utile de vérifier également la zone de transit pour voir si un blob est référencé. J'ai modifié le script bash d'origine pour ce faire et j'ai trouvé ce qui faisait référence à un blob corrompu dans mon référentiel:
la source
Donc ... j'avais besoin de trouver tous les fichiers dépassant une limite donnée dans un dépôt de plus de 8 Go, avec plus de 108 000 révisions. J'ai adapté le script perl d'Aristote avec un script ruby que j'ai écrit pour atteindre cette solution complète.
Premièrement,
git gc
- faites ceci pour vous assurer que tous les objets sont dans des fichiers pack - nous n'analysons pas les objets qui ne sont pas dans des fichiers pack.Suivant Exécutez ce script pour localiser tous les objets blob sur des octets CUTOFF_SIZE. Capturez la sortie dans un fichier comme "large-blobs.log"
Ensuite, modifiez le fichier pour supprimer tous les objets blob que vous n'attendez pas et les bits INPUT_THREAD en haut. une fois que vous n'avez que des lignes pour les sha1 que vous voulez trouver, exécutez le script suivant comme ceci:
Où le
git-find-blob
script est ci-dessous.La sortie ressemblera à ceci:
Etc. Chaque commit contenant un gros fichier dans son arborescence sera répertorié. si vous
grep
sortez les lignes qui commencent par un onglet, etuniq
que, vous aurez une liste de tous les chemins que vous pouvez filtrer-branche à supprimer, ou vous pouvez faire quelque chose de plus compliqué.Permettez-moi de répéter: ce processus s'est déroulé avec succès, sur un dépôt de 10 Go avec 108 000 validations. Cela a pris beaucoup plus de temps que je ne l'avais prédit lors de l'exécution sur un grand nombre de blobs, cependant, plus de 10 heures, je devrai voir si le bit de mémorisation fonctionne ...
la source
-- --all
. (Il est important de trouver tous les commits à l'échelle du référentiel dans des cas tels que la suppression complète d'un fichier volumineux de l'historique du référentiel ).De plus
git describe
, que je mentionne dans ma réponse précédente ,git log
etgit diff
bénéficie désormais également de l'--find-object=<object-id>
option " " pour limiter les résultats aux changements qui impliquent l'objet nommé.C'est dans Git 2.16.x / 2.17 (Q1 2018)
Voir commit 4d8c51a , commit 5e50525 , commit 15af58c , commit cf63051 , commit c1ddc46 , commit 929ed70 (4 janvier 2018) par Stefan Beller (
stefanbeller
) .(Fusionné par Junio C Hamano -
gitster
- in commit c0d75f0 , 23 janv.2018 )la source