web-dev-qa-db-fra.com

git rebase sans changer les horodatages de commit

Serait-il logique d'exécuter git rebase tout en préservant les horodatages de validation?

Je crois que la conséquence serait que la nouvelle succursale n'aura pas nécessairement de dates de validation chronologiquement. Est-ce théoriquement possible? (par exemple en utilisant des commandes de plomberie; juste curieux ici)

S'il est théoriquement possible, est-il possible en pratique avec rebase, de ne pas modifier les horodatages?

Par exemple, supposons que j'ai l'arborescence suivante:

master <jun 2010>
  |
  :
  :
  :     oldbranch <feb 1984>
  :     /
oldcommit <jan 1984>

Maintenant, si je rebase oldbranch le master, la date du commit change de février 1984 à juin 2010. Est-il possible de changer ce comportement pour que l'horodatage du commit ne soit pas modifié? Au final j'obtiendrais ainsi:

      oldbranch <feb 1984>
      /
 master <jun 2010>
    |
    :

Est-ce que cela aurait du sens? Est-il même permis à git d'avoir un historique où un ancien commit a un commit plus récent en tant que parent?

139
Olivier Verdier

Une question cruciale de Von C m'a aidé à comprendre ce qui se passe: lorsque votre rebase, l'horodatage du committer change, mais pas l'horodatage de l'auteur, qui soudainement a du sens. Ma question n'était donc pas suffisamment précise.

La réponse est que le rebase ne change en fait pas les horodatages de l'auteur (vous n'avez rien à faire pour cela), ce qui me convient parfaitement.

30
Olivier Verdier

Mise à jour de juin 2014: David Fraser mentionne dans les commentaires une solution également détaillée dans " Modifier les horodatages lors du rebasage de la branche git ", en utilisant l'option --committer-date-is-author-date (Introduit initialement en janvier 2009 dans commit 3f01ad6

Notez que l'option --committer-date-is-author-date Semble laisser l'horodatage de l'auteur et définir l'horodatage du committer pour qu'il soit le même que l'horodatage de l'auteur d'origine, ce que voulait OP Olivier Verdier .

J'ai trouvé le dernier commit avec la date correcte et j'ai fait:

git rebase --committer-date-is-author-date SHA

Voir git am :

--committer-date-is-author-date

Par défaut, la commande enregistre la date du message électronique comme date de l'auteur de la validation et utilise l'heure de la création de la validation comme date de validation.
Cela permet à l'utilisateur de mentir sur la date du committer en utilisant la même valeur que la date de l'auteur .


(Réponse originale, juin 2012)

Vous pouvez essayer, pour un non interactif rebase

git rebase --ignore-date

(à partir de cela réponse SO )

Ceci est transmis à git am , qui mentionne:

 --ignore-date

Par défaut, la commande enregistre la date du message électronique comme date de l'auteur de la validation et utilise l'heure de la création de la validation comme date de validation.
Cela permet à l'utilisateur de mentir sur la date de l'auteur en utilisant la même valeur que la date de validation.

Pour git rebase , cette option est "incompatible avec l'option --interactive".

Depuis vous pouvez modifier à volonté l'horodatage de l'ancienne date de validation (avec git filter-branch ), je suppose que vous pouvez organiser votre historique Git avec l'ordre de la date de validation que vous souhaitez envie/besoin, même placez-le dans le futur! .


Comme Olivier le mentionne dans sa question, la date de l'auteur n'est jamais modifiée par un rebase;
Extrait du Pro Git Book :

  • L'auteur est la personne qui a initialement écrit l'œuvre,
  • tandis que le committer est la dernière personne à avoir appliqué le travail.

Donc, si vous envoyez un patch à un projet et que l'un des membres principaux applique le patch, vous obtenez tous les deux un crédit.

Pour être plus clair, dans ce cas, comme le commente Olivier:

le --ignore-date fait le contraire de ce que j'essayais de réaliser !
À savoir, il efface l'horodatage de l'auteur et les remplace par les horodatages de validation!
La bonne réponse à ma question est donc:
Ne faites rien, car git rebase Ne modifie pas par défaut l'horodatage des auteurs.


131
VonC

Si vous avez déjà bousillé les dates de validation (peut-être avec un rebase) et que vous souhaitez les réinitialiser à leurs dates d'auteur correspondantes, vous pouvez exécuter:

git filter-branch --env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; export GIT_COMMITTER_DATE'

114
Andy

Par défaut, git rebase définira l'horodatage du committer au moment où le nouveau commit est créé, mais gardera l'horodatage de l'auteur intact. La plupart du temps, c'est le comportement souhaité, mais dans certains scénarios, nous ne souhaitons pas non plus modifier l'horodatage du commiter. Comment pouvons-nous y parvenir? Eh bien, voici l'astuce que je fais habituellement.

Tout d'abord, assurez-vous que chacune des validations que vous êtes sur le point de rebaser a un message de validation unique et un horodatage d'auteur (c'est là que l'astuce doit être améliorée, mais elle convient actuellement à mes besoins).

Avant le rebase, enregistrez l'horodatage du committer, l'horodatage de l'auteur et le message de commit de tous les commits qui seront rebasés dans un fichier.

#NOTE: BASE is the commit where your rebase begins
git log --pretty='%ct %at %s' BASE..HEAD > hashlog

Ensuite, laissez le rebase réel avoir lieu.

Enfin, nous remplaçons l'horodatage du committer actuel par celui enregistré dans le fichier si le message de commit est le même en utilisant git filter-branch.

 git filter-branch --env-filter '__date=$(__log=$(git log -1 --pretty="%at %s" $GIT_COMMIT); grep -m 1 "$__log" ../../hashlog | cut -d" " -f1); test -n "$__date" && export GIT_COMMITTER_DATE=$__date || cat'

En cas de problème, passez à la caisse git reflog ou tous les refs/original/ réfs.

De plus, vous pouvez faire la même chose avec l'horodatage de l'auteur.

Par exemple, si l'horodatage de l'auteur de certaines validations est hors service, et sans réorganiser ces validations, nous voulons simplement que l'horodatage de l'auteur s'affiche dans l'ordre, les commandes suivantes vous aideront.

git log --pretty='%at %s' COMMIT1..COMMIT2 > hashlog
join -1 1 -2 1 <(cat hashlog | cut -f 1 | sort -nr | awk '{ print NR" "$1 }') <(cat hashlog | awk '{ print NR" "$0 }') | cut -d" " -f2,4- > hashlog_
mv hashlog_ hashlog
git filter-branch --env-filter '__date=$(__log=$(git log -1 --pretty="%s" $GIT_COMMIT); grep -m 1 "$__log" ../../hashlog | cut -d" " -f1); test -n "$__date" && export GIT_AUTHOR_DATE=$__date || cat'
14
weynhamz