Existe-t-il un moyen dans git d'obtenir une date de poussée pour un commit donné?

91

Je me demande s'il existe un moyen d'afficher une date push associée à chaque commit dans le journal git. Si ce n'est pas possible, existe-t-il un moyen de voir tous les commits sous une certaine poussée.

J'écris un programme qui doit garder une trace des commits lorsqu'ils sont poussés. Étant donné que le journal git est trié par date de validation, pas par date de transmission, je ne suis pas en mesure de voir les validations les plus récentes qui sont transmises. Par exemple, si un utilisateur s'engage dans son référentiel local 2 jours avant de pousser vers le maître, ce commit sera placé derrière 2 jours d'autres validations dans le journal du référentiel maître.

justkikuchi
la source

Réponses:

77

Il m'a fallu un temps incroyablement long pour rassembler des informations éparses et enfin trouver la meilleure réponse à cette question, mais maintenant je sais que je l'ai. En seulement deux lignes, sans code et sans hook:

# required for a bare repo
git config core.logAllRefUpdates true

git reflog --date=local master

Simple enfin.

Attention: vous souhaitez probablement remplacer les valeurs par défaut de gc.reflogExpireet gc.reflogExpireUnreachable. Vérifiez les git help reflogdétails et comprenez comment et pourquoi cela fonctionne.

Les deux commandes ci-dessus doivent être exécutées dans le clone vers lequel vous poussez . Si cela n'est pas possible, une approximation consiste à exécuter un autre clone permanent :

git fetch               origin        # often and *regularly*
git reflog --date=local origin/master

Ne supprimez jamais ce clone permanent ou vous perdrez les dates.

Mars
la source
2
Je voudrais ajouter que dans mon cas, je devais faire git reflog --date=local origin/master(note origin/) pour voir la liste des poussées. Sinon, seuls les validations, les extractions et les extractions étaient dans la liste (ce qui est également utile). En fait, j'ai été signalé par la réponse de @ JonathanDay .
NIA
@NIA: origin / master ne vous donnera qu'une approximation. J'ai mis à jour ma réponse suite à votre commentaire, est-ce que cela clarifie?
MarcH
37

Git est un système de contrôle de version distribué, vous devez donc définir soigneusement ce que vous entendez par "date de diffusion". Par exemple, supposons que l'utilisateur A envoie des validations dans le référentiel de l'utilisateur B. Un peu plus tard, l'utilisateur B pousse ces mêmes validations vers un troisième référentiel. Quelle date vous intéresse?

Je suppose que vous avez un référentiel partagé et que vous voulez que les utilisateurs de ce référentiel partagé puissent déterminer quand quelque chose a été publié dans le référentiel. Si c'est vrai, vous devrez collecter ces informations dans le référentiel partagé.

Les mauvaises nouvelles

Malheureusement, il n'y a aucun moyen d'ajouter la date aux messages de validation. Cela changerait l'ID de validation (qui est un hachage SHA1 du contenu), causant toutes sortes de problèmes.

La bonne nouvelle

Heureusement, Git a une fonctionnalité (relativement nouvelle) appelée notes . Cette fonctionnalité vous permet d'attacher du texte arbitraire aux commits, qui git logpeuvent s'afficher. Les notes peuvent être modifiées et partagées avec d'autres.

Vous pouvez utiliser la fonction de notes pour joindre un message «Cette validation a été reçue le [date]» à chaque validation telle qu'elle est reçue par le référentiel partagé.

Voir git help notespour plus de détails.

Comment enregistrer la date

Voici l'approche que je recommande:

  1. Modifiez le post-receivehook de votre référentiel partagé pour parcourir chaque commit nouvellement accessible pour chaque référence mise à jour.
  2. Pour chaque commit, ajoutez quelque chose comme "[utilisateur] de [repository_url] a ajouté ce commit à [ref] le [date]" à la note du commit.

    Vous pouvez utiliser une référence de notes dédiée à cet effet (comme refs/notes/received-on) au lieu de la référence par défaut refs/notes/commits. Cela évitera les conflits avec les notes créées à d'autres fins.

  3. Modifiez votre receivehook pour refuser les mises à jour de la référence de vos notes (pour empêcher les utilisateurs de jouer accidentellement ou intentionnellement avec les notes).
  4. Dites à tous les utilisateurs d'exécuter les commandes suivantes depuis leur arbre de travail:

    # Fetch all notes from the shared repository.
    # Assumes the shared repository remote is named 'origin'.
    git config --add remote.origin.fetch '+refs/notes/*:refs/remote-notes/origin/*'
    
    # Show all notes from the shared repository when running 'git log'
    git config --add notes.displayRef 'refs/remote-notes/origin/*'
    

    Cette étape est nécessaire car Git ignore par défaut les références sans branche et sans balise dans les référentiels en amont.

Ce qui précède suppose que les références sont uniquement avancées, jamais supprimées ou mises à jour de force. Vous voudrez probablement que le post-receivecrochet ajoute également des notes «supprimé le [date]» pour gérer ces cas.

Richard Hansen
la source
J'ai utilisé votre idée dans mon blog mnaoumov.wordpress.com/2013/01/31/git-get-push-date
mnaoumov
7
git reflog show origin/master --pretty='%h %gd %gs %s' --date=iso

Cela semble fonctionner assez bien pour moi. La date de validation (% cd) est trompeuse car elle n'est pas nécessairement la même que la date d'envoi. L'option --date = iso, cependant , affichera la date push / fetch .

Notez que si vous avez récupéré à partir de l'origine / maître, il imprimera la date à laquelle vous l'avez récupéré; PAS la date à laquelle quelqu'un d'autre a poussé la validation.

 - %h:  abrev. hash
 - %gd: human readable reflog selector
 - %gs: reflog subject
 - %s:  subject/commit message

Bonus: vous pouvez bien sûr faire un formatage plus joli. Jusqu'à présent, j'aime ce code couleur. C'est un peu difficile à taper cependant. Cela donnera le SHA au rouge, le sélecteur de reflog au cyan et le reflog au vert.

git reflog show origin/master --pretty='format:%C(red)%h%Creset %C(cyan)%gd%Creset %C(green)%gs%Creset: %s' --date=iso
VC
la source
Salut VC cela signifie-t-il que si la sortie de la commande "reflog show origin / master --pretty = '% Cred% h% Creset -% C (yellow)% gd% Creset% Cblue (% gs)% Creset% s' - -date = iso "est" da4c192cd -origin / master @ {2019-02-07 08:13:40 +0100} (pull: avance rapide) JIRA-2542 améliore le rapport de test ", cela signifie alors le contenu de ma branche JIRA -2542 a été fusionné sur l'origine / maître par un fast-froward à 2019-02-07 08:13:40?
Simon
Salut Simon, oui. Vous avez fait un pull git sur votre branche et elle a été fusionnée sur origin / master via une avance rapide à ce moment-là.
VC
Cela ne fonctionne que sur le référentiel de l'auteur. Si je clone un référentiel, la valeur est vide. Vous ne pouvez pas voir le temps de poussée des autres.
ramwin le
6

Jetez un œil à git reflog show master. Probablement pas le format exact que vous souhaitez, mais devrait vous orienter dans la bonne direction.

Une autre idée consiste à exécuter un script dans un crochet push.

Karl Bielefeldt
la source
J'ai pensé à lancer le push hook, mais il semble que cela devrait être un dernier effort. Avec un hook, il semble que chaque utilisateur devrait avoir ce hook dans chacun de ses référentiels. Pouvez-vous être plus précis sur le git reflog show master? Je souhaite pouvoir afficher la date de diffusion des validations individuelles de chaque utilisateur.
justkikuchi
git reflog montre l' ordre des changements dans le repo dans lequel vous l'exécutez. Je ne suis pas sûr qu'il existe un moyen direct d'obtenir la date, mais .git/logs/refs/heads/masteril montre un horodatage.
Karl Bielefeldt
3
Quant aux crochets, il y a des crochets de réception qui fonctionnent sur la machine que vous poussez à . Puisque le push n'est pertinent que par rapport à un dépôt spécifique, je suppose que vous avez un certain repo "béni" sur lequel vous voulez l'exécuter. Il en va de même git reflogpour cette question.
Karl Bielefeldt
5

Cette réponse concernant l'inspection du reflog sur la télécommande pourrait aider ( https://stackoverflow.com/a/8791295/336905 ) en vous donnant des informations sur quelle branche a été poussée même à travers elle ne montre pas quels commits ont été poussés, mais vous pourrait inter-corréler en trouvant la prochaine poussée après la date de validation locale. Pas infaillible, mais pratique si vous n'avez pas déjà implémenté l'excellente suggestion de notes de @RichardHansen publiée plus tôt

Jonathan Day
la source
1
Avec une note que reflog de origin/branchne montrera que les changements effectués sur la machine actuelle , c'est extrêmement utile! Pour une utilisation quotidienne, je ne veux pas implémenter de hooks, donc pour une simple question "Hmmm, quand j'ai poussé ce commit la semaine dernière?" - cela fonctionne très bien.
NIA
4

Vous pouvez également consulter l'heure de modification du fichier du fichier objet de validation dans le répertoire "objects" du référentiel git sur le serveur lui-même.

Riches
la source
2

Pourquoi git AuthorDate est-il différent de CommitDate?

  • AuthorDate correspond à la première création du commit.
  • CommitDate correspond à la dernière modification du commit (ex: rebase).

Vous pouvez les obtenir avec les --prettyoptions de formatage:

       o    %cd: committer date
       o    %cD: committer date, RFC2822 style
       o    %cr: committer date, relative
       o    %ct: committer date, UNIX timestamp
       o    %ci: committer date, ISO 8601 format

Donc, si vous et d'autres développeurs faites git rebase avant git push, vous vous retrouverez avec une date de validation postérieure à la date de l' auteur .

Cette commande affiche la date de validation: git log --pretty=fuller

Dnozay
la source
1

Je suppose que vous pouvez utiliser la notation suivante pour obtenir la date d'envoi: git log -g --date = local

Pashh PGH
la source