git rebase sin cambiar las marcas de tiempo de confirmación


¿Tendría sentido realizar git rebase mientras se preservan las marcas de tiempo de confirmación?

Creo que una consecuencia sería que la nueva rama no necesariamente tendrá fechas de confirmación cronológicamente. ¿Es eso teóricamente posible en absoluto? (por ejemplo, usando comandos de fontanería; solo curioso aquí)

Si es teóricamente posible, entonces es posible en la práctica con rebase, no cambiar las marcas de tiempo?

Por ejemplo, supongamos que tengo lo siguiente árbol:

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

Ahora, si rebase oldbranch en master, la fecha de la confirmación cambia de febrero de 1984 a junio de 2010. ¿Es posible cambiar ese comportamiento para que la marca de tiempo de confirmación no se cambie? Al final obtendría:

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

¿Tendría sentido en absoluto? ¿Está permitido en git tener un historial donde una confirmación antigua tiene una confirmación más reciente como padre?

Author: Olivier Verdier, 2010-06-04

4 answers

Actualización de junio de 2014: David Fraser menciona en los comentarios una solución también detallada en " Cambiar las marcas de tiempo al cambiar la base de git branch ", usando la opción --committer-date-is-author-date (introducida inicialmente en enero. 2009 en commit 3f01ad6

Tenga en cuenta que la opción --committer-date-is-author-dateparece dejar la marca de tiempo del autor, y establecer la marca de tiempo del committer para que sea la misma que la marca de tiempo del autor original, que es lo que el OP Olivier Verdier quería.

Encontré la última confirmación con la fecha correcta y lo hice:

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

Véase git am:

--committer-date-is-author-date

De forma predeterminada, el comando registra la fecha del mensaje de correo electrónico como la fecha del autor de la confirmación, y usa la hora de creación de la confirmación como la fecha de la confirmación.
Esto permite al usuario mentir sobre la fecha del committer usando el mismo valor que la fecha del autor .


(Respuesta original, junio de 2012)

Usted podría intentar, para un no interactivo rebase

git rebase --ignore-date

(de esto ASÍ que respuesta)

Esto se pasa a git am, que menciona:

 --ignore-date

De forma predeterminada, el comando registra la fecha del mensaje de correo electrónico como la fecha del autor de la confirmación, y usa la hora de creación de la confirmación como la fecha de la confirmación.
Esto permite al usuario mentir sobre la fecha del autor usando el mismo valor que la fecha del committer.

Para git rebase, esta opción es "Incompatible con la opción interactive interactive."

Desde puede cambiar a voluntad la marca de tiempo de la fecha de confirmación anterior (con git filter-branch), Supongo que puedes organizar tu historial de Git con cualquier orden de fecha de confirmación que quieras / necesites, incluso ¡ponlo en el futuro!.


Como Olivier menciona en su pregunta, la fecha de autor nunca se cambia por una rebase; {[36]]} Desde el Libro Pro Git :

  • El autor es la persona que originalmente escribió la obra,
  • mientras que el committer es la persona que aplicó el trabajo por última vez.

Por lo tanto, si envía un parche a un proyecto y uno de los miembros del núcleo aplica el parche, ambos obtienen crédito.

Para ser extra claro, en este caso, como Olivier comenta:

El --ignore-date hace lo contrario de lo que yo estaba tratando de lograr!
Es decir, borra la marca de tiempo del autor y los reemplaza con las marcas de tiempo de commits!
Así que la respuesta correcta a mi pregunta es:
No haga nada, ya que git rebase en realidad no cambia las marcas de tiempo de los autores por defecto.


 113
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:01

Si ya has estropeado las fechas de confirmación (tal vez con un rebase) y quieres restablecerlas a sus fechas de autor para correspondencia, puedes ejecutar:

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

 109
Author: Andy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-08 18:00:27

Una pregunta crucial de Von C me ayudó a entender lo que está pasando: cuando tu rebase, la marca de tiempo del committer cambia, pero no la marca de tiempo del autor, que de repente todo tiene sentido. Así que mi pregunta no era lo suficientemente precisa.

La respuesta es que rebase en realidad no cambia las marcas de tiempo del autor (no necesitas hacer nada para eso), lo que me conviene perfectamente.

 28
Author: Olivier Verdier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-14 08:31:35

De forma predeterminada, git rebase establecerá la marca de tiempo del committer a la hora en que se crea una nueva confirmación, pero mantén intacta la marca de tiempo del autor. La mayor parte del tiempo, este es el comportamiento deseado, pero en algunos escenarios, no deseamos cambiar la marca de tiempo del commiter tampoco. ¿Cómo podemos lograr eso? Bueno, aquí está el truco que suelo hacer.

En primer lugar, asegúrese de que cada una de las confirmaciones que está a punto de rebase tiene un único mensaje de confirmación y marca de tiempo del autor (Aquí es donde trick necesita mejoras, actualmente se adapta a mis necesidades sin embargo).

Antes de la rebase, registre la marca de tiempo del committer, la marca de tiempo del autor y el mensaje de confirmación de todas las confirmaciones que serán rebasadas a un archivo.

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

Entonces, deja que la rebase real tenga lugar.

Finalmente, reemplazamos la marca de tiempo del committer actual con la registrada en el archivo si el mensaje de commit es el mismo usando 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'

Si algo sale mal, simplemente checkout git reflog o todos los refs/original/ árbitros.

Además, puedes hacer algo similar a la marca de tiempo del autor.

Por ejemplo, si la marca de tiempo del autor de algunas confirmaciones está fuera de orden, y sin reorganizar estas confirmaciones, solo queremos que la marca de tiempo del autor se muestre en orden, a continuación, los siguientes comandos le ayudará.

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'
 12
Author: weynhamz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-17 02:56:15