2015-07-16 1 views
3

J'ai une situation où j'ai fusionné quelques années de validations dans un référentiel. L'un des commits avait un commentaire qui était une pâte d'un journal Address Sanitizer lié au correctif.Pourquoi une branche de filtre sans opération crée-t-elle une divergence, et comment puis-je résoudre ce problème?

Cela ne semble pas si mal, sauf adresse journaux Sanitizer ressembler à ceci:

==10856==ERROR: AddressSanitizer: heap-buffer-overflow on address 
0x62a00000b201 at pc 0x47df61 bp 0x7fffffff2ca0 sp 0x7fffffff2c98 
READ of size 1 at 0x62a00000b201 thread T0 
#0 0x47df60 in Expand_Series ../src/core/m-series.c:145 
#1 0x47e5a7 in Extend_Series ../src/core/m-series.c:187 
#2 0x466e0c in Scan_Quote ../src/core/l-scan.c:462 
#3 0x46a797 in Scan_Token ../src/core/l-scan.c:918 
#4 0x46e263 in Scan_Block ../src/core/l-scan.c:1188 
... 

Et il va jusqu'à # 250 ou dans ce cas. GitHub analyse les motifs #XXX et s'ils correspondent à un numéro de problème, mettez une note à propos de la mention sur le problème référencé. Alors soudain, GitHub pense que ce commit est en train de faire des remarques sur tous les problèmes et toutes les demandes, et le fera pendant un certain temps.

Je pensais que je venais d'utiliser un git filter-branch que je ne me dérange vraiment casser de l'histoire (je devais faire un filtre déjà branche pour se débarrasser de certaines choses que je ne voulais pas). Cependant, j'ai fait cette autre branche de filtre avant que je fasse une fusion et ai continué avec le travail. Maintenant que j'ai remarqué cette apparition dans GitHub, je voudrais revenir en arrière et le réécrire et ne me dérange pas si chaque commit sur chaque branche après ce point obtient un nouveau hachage. C'est bon pour moi. La réécriture Je me suis mis au travail, mais ce que je n'arrive pas à comprendre, c'est pourquoi il y a tellement de divergence. Il semble avoir fait de la réécriture qui affecte les choses avant d'apporter des changements au commentaire. En tant que test simple, j'ai essayé ce que je pensais devrait être un no-op:

git filter-branch -f --msg-filter 'sed "s/a/a/g"' -- --all 

Je ne suis pas personne sed, mais je crois comprendre que cela refaire tous les messages de validation et de remplacer a avec a. (Rand Ayn serait heureux.)

Il ne diverge pas autant commits que mon remplacement effectif ... 600 au lieu de 1000. Mais qu'il diverge tout indique que j'ai une sorte de malentendu. Comment est-ce que je peux réécrire that commit message in the history sans endommager tous les commits en dehors de ceux qui se produisent après lui ... et obtenir l'effet sur toutes les branches?

+0

https://rtyley.github.io/bfg-repo-cleaner/#examples avec '--replace-Text' pour la prochaine fois –

Répondre

2

Il y a un endroit supplémentaire qui pourrait être le coupable (et était dans mon cas). Tenir compte:

$ git cat-file -p 20b9cd59c6c6a1a2bccfb2ddb9af68c083a28698 
tree dee80bcd856b23aceb8946473bf64d9aef0fe629 
parent b12dc8b9388dc0a2ae34563426043a612d296195 
author XXX <[email protected]> 1355477802 +0200 
committer XXX <[email protected]> 1355478447 +0200 
encoding cp1251 

Add (literally) three characters to one file that will 
inadvertently create hours of fun for people years later. 

Il est l'encodage, dans ce cas Windows 1251. La personne qui l'a trouvé le résume ainsi:

msg-filtre obtient le message brut, aucun codage méta-informations. Ainsi, même lorsque vous utilisez un filtre de messages transparent 8 bits (tel qu'un chat ordinaire ), la validation recréée ne contient pas cette méta-information de codage .

(qui est légèrement imprécis, car le filtre obtient l'encodage informations, il pourrait le lire via la variable d'env GIT_COMMIT. Il est la sortie, qui ne contrôle pas l'encodage. Au moins, je ne sais comment. ..

Il a corrigé le désordre général dans notre situation particulière en utilisant Graft Points. C'est au-delà de mes connaissances actuelles en git, donc je ne vais pas essayer de l'expliquer.

+0

Wow, ouch. La validation a été modifiée en supprimant l'encodage. Cela ressemble à un bug de type filtre, pas qu'il puisse fournir autant d'aide que l'on voudrait, mais il pourrait au moins extraire l'encodage du message et le placer dans une variable d'environnement de sorte qu'un filtre propre de 8 bits le conserve! – torek

+0

@torek Jolie sournoise. Je me demande s'il y a un bon moyen d'empêcher de tels encodages de glisser? Accepter cela puisque c'était le problème dans mon cas, mais merci encore pour votre réponse approfondie ... – HostileFork

4

S'il y a un message existant qui ne pas fin avec un saut de ligne, sed ajoutera un (au moins certaines versions de sed, y compris celui que je testé ici):

$ printf 'foo\nbar' 
foo 
bar$ printf 'foo\nbar' | sed 's/a/a/' 
foo 
bar 
$ 

qui signifie que votre Le filtre de message test peut avoir modifié un message. Sur la base de vos résultats, je suppose qu'au moins un commit, environ 600 validations à partir de quelques conseils de branche, a été modifié de cette façon. (Je l'ai vu exactement ce problème moi-même avant.)

(Une autre possibilité est une sorte de normalisation Unicode, bien que je ne l'ai pas vu cela avec sed.)

À supposer que c'est le cas, l'affaire car vous devrez trouver une commande qui n'affecte pas les autres validations. Une bonne solution consiste à utiliser la variable d'environnement $GIT_COMMIT pour identifier le (s) commit (s) à toucher, et assurez-vous de faire quelque chose qui soit vraiment non-op (un cat msg-filter pourrait fonctionner mieux que sed, par exemple) sur tous les autres engage:

Comme pour obtenir l'effet sur toutes les branches, votre -- --alldevrait faire l'affaire déjà.


On dirait que vous savez déjà pourquoi les commits restants obtiennent de nouveaux SHA-1, mais juste pour être complet, je comprendront aussi. Vous pouvez passer cette partie, c'est ici pour les autres personnes qui lisent la question.

Si un commit est modifié, il obtient un nouveau SHA-1 (par définition, puisque le SHA-1 est la somme de contrôle du contenu de la validation). Pas grand-chose jusqu'à présent, mais disons qu'il ya seulement cinq commits (tous sur le maître dans ce cas, pas que cela importe) et nous modifierons celui du milieu avec un filtre-branche de filtre:

A <- B <- C <- D <- E  [original] 

Entre Nous dire le SHA-1 réel pour C commence par 30001). Maintenant, nous allons construire un résultat partiel, au milieu de l'opération de branche de filtre:

A <- B <- C' 

Disons que, par une coïncidence étrange, le nouveau SHA-1 commence par 30002, version 2 de Commit 3.

Jetons un coup d'oeil à (une partie de) engager originale D:

$ git cat-file -p HEAD^ 
tree 954019cba5244a4a135ff62258660b3d2e3a8087 
parent 30001... 

commit D fait référence, par numéro, en vue de commettre C. Alors filter-branch, alors que cela ne change rien autre au sujet D, doit construire une nouvelle commettras D' qui dit parent 30002...:

A <- B <- C' <- D' 

De même, filter-branch est forcé de copier vieux commettre E à nouveau E':

A <- B <- C' <- D' <- E'  [replacement] 

Par conséquent, tout filter-branch qui modifie certains commit, modifie également tous les commits suivants. En fait, git rebase et git filter-branch sont des sortes de cousins.Il suffit de lire les validations existantes, d'appliquer des changements, et d'écrire les résultats en tant que nouveaux commits, branche de filtre le fait tous par programmation-ie , n'a pas de mode --interactive et a un ensemble de spécifications très large et complexe pour effectuer des modifications, et peut ensuite l'appliquer à plusieurs branches, au lieu d'une seule branche.)

+0

Great information, merci! Même les choses que je connaissais, pour la postérité de la recherche ... une bonne forme (il y en aura plus d'ordres de grandeur qu'il n'y en a de moi). :-) On dirait que vous avez presque certainement raison ... et je voulais y aller aujourd'hui, mais il semble que je ne puisse pas le faire. Je rapporterai quand je ferai ... – HostileFork

+0

Eh bien, en revenant à cela, il s'est avéré être un peu plus compliqué avec [encodage de caractères] (http://stackoverflow.com/a/31601082/211160) ...! Je ne sais pas combien de temps il m'aurait fallu pour trouver ça tout seul. : -/ – HostileFork