¿Cómo puedo obtener la diferencia entre todas las confirmaciones que ocurrieron entre dos fechas con Git?

116

¿O solo todas las confirmaciones que ocurrieron entre dos fechas? En SVN, podrías hacer algo como

svn diff -r{date}:{date}

¡para hacerlo! Parece que no puedo encontrar un Git equivalente a esto.

Específicamente, estoy buscando escribir un script para enviar correos electrónicos diarios con todo el código comprometido ese día y por quién.

Chris
fuente

Respuestas:

159

Podrías usar git whatchanged --since="1 day ago" -p

También se necesita un --untilargumento.

Docs

seth
fuente
¡Gracias! Esto era justo lo que quería, incluso toma el parámetro --committer, ¡aunque eso no aparece en su documentación! ¡Además, 'git whatchanged' no apareció en 'git help'! No tengo idea de por qué ... gracias de nuevo.
Chris
5
Deberías hacer de esta tu respuesta elegida para que Seth reciba algo de karma.
Scott
18
@brbob Sé que esto fue respondido hace mucho tiempo, pero solo para alguien que se topa con esto (como lo hice yo) La ayuda de Git dice: The command is kept primarily for historical reasons; fingers of many people who learned Git long before git log was invented by reading Linux kernel mailing list are trained to type it. Entonces, los documentos alientan a usar en git loglugar de git whatchanged; este último comando también usa la opción --no-merge de git log, por lo que generan los mismos resultados.
Ramses
2
git whatchanged es una especie de alias del comando git log de acuerdo con el documento de git log
Vincent
2
git whatchangedestá en desuso a partir de la última versión actual 2.21.0. Todo lo git whatchangedlogrado se puede lograr git logy solo se conserva por razones históricas. Ver detalles git-scm.com/docs/git-whatchanged/2.21.0
Devy
60

Las sugerencias anteriores tienen algunos inconvenientes. Básicamente, estaba buscando algo equivalente a cvs diff -D"1 day ago" -D"2010-02-29 11:11". Mientras recopilaba más y más información, encontré una solución.

Cosas que he probado:

  • git whatchanged --since="1 day ago" -pdesde aqui

    Pero esto da una diferencia para cada confirmación, incluso si hay varias confirmaciones en un archivo. Sé que "fecha" es un concepto un tanto vago en git , pensé que debía haber alguna forma de hacer esto.

  • git diff 'master@{1 day ago}..masterda alguna advertencia warning: Log for 'master' only goes back to Tue, 16 Mar 2010 14:17:32 +0100.y no muestra todas las diferencias.

  • git format-patch --since=yesterday --stdout no da nada por mi.

  • revs=$(git log --pretty="format:%H" --since="1 day ago");git diff $(echo "$revs"|tail -n1) $(echo "$revs"|head -n1) funciona de alguna manera, pero parece complicado y no se limita a la rama actual.

Finalmente:

Curiosamente, git-cvsserver no admite "cvs diff -D" (sin que esté documentado en alguna parte).

Weidenrinde
fuente
4
+1 para git rev-list, lo que contribuyó en gran medida a resolver un problema muy similar que estaba viendo.
yo_y
Esta no debería ser la respuesta aceptada, la de seth es más concisa y correcta.
ctford
6
@ctford, en mi opinión, no es correcto. Puede informar múltiples diferencias para un archivo, no una diferencia por archivo como svn / cvs diff.
Weidenrinde
1
@Weidenrinde +1, esto es mucho más inteligente
rostamn739
1
La git diff 'master@{1 day ago}..mastersintaxis significa "verifique el reflog y averigüe dónde mastersolía apuntar la rama en su repositorio local 1 day ago ". Específicamente, no utilizará el historial de confirmaciones real de la rama actual master. Esto rara vez es lo que realmente desea.
Mikko Rantalainen
22

"fecha" es un concepto un tanto vago en git. Una confirmación tendrá una fecha de autor que puede ser un poco en el pasado antes de que alguien realmente extraiga / confirme la confirmación en su repositorio, también la confirmación puede volver a basarse y actualizarse para estar encima de una confirmación aparentemente más nueva.

Una confirmación también tiene una fecha de confirmación que se actualiza si una confirmación se vuelve a basar o se modifica de alguna manera. Es más probable que estas confirmaciones estén en algún tipo de orden cronológico, pero aún estás a merced de que el autor de la confirmación tenga la hora correcta configurada en su computadora y, aun así, una confirmación no modificada puede ubicarse en una rama de características en un repositorio remoto indefinidamente antes fusionándose en la rama maestra de un repositorio central.

Lo que probablemente sea más útil para sus propósitos es la fecha de re-registro en el repositorio particular en cuestión. Si tiene habilitados los reflogs por rama (consulte git config core.logAllRefUpdates), puede usar la ref@{date}sintaxis para referirse a dónde estaba una rama en un momento determinado.

P.ej

git log -p master@{2009-07-01}..master@{now}

También puede usar descripciones 'difusas' como:

git log -p "master@{1 month ago}..master@{yesterday}"

Estos comandos mostrarán todas las confirmaciones que han "aparecido" en la rama dada del repositorio, independientemente de la "antigüedad" que tengan según su autor y las fechas de confirmación.

Tenga en cuenta que el reflog por rama es específico de un repositorio, por lo que si está ejecutando el comando de registro en un clon y no extrae durante (digamos) un mes, extraiga todos los cambios del último mes a la vez, luego, todos los cambios del último mes aparecerán en un @{1 hour ago}..@{now}rango. Si puede ejecutar el comando de registro en el repositorio 'central' al que la gente empuja, entonces puede hacer lo que quiera.

CB Bailey
fuente
Muy buena redacción y buena respuesta a la pregunta formulada ... pero creo que no ayudaría mucho a hacer lo que pretendía brbob.
Jakub Narębski
Depende, podría ayudar si realmente quiere analizar lo que se envió a una determinada rama en un determinado repositorio central y el comando de registro se ejecutó en ese repositorio. Creo que una edición está en orden ...
CB Bailey
"fecha de compromiso que se actualiza si un compromiso se vuelve a basar o se modifica de alguna manera", en realidad la fecha nunca se cambia; toda la confirmación se reemplaza con otra confirmación (aunque el árbol supuestamente podría ser el mismo).
Hasen
2
@hasen j: Técnicamente, tienes razón. Las confirmaciones son inmutables. Cuando modificas o modificas una confirmación y creas una nueva confirmación, el mensaje de confirmación existente, los detalles del autor y la fecha del autor a menudo se copian de la confirmación anterior, por lo que es como si estuvieras actualizando la confirmación con una nueva identificación de confirmación y fecha de confirmación.
CB Bailey
Tenga en cuenta que la @{time spec}sintaxis siempre se refiere a su reflog local . No se refiere al historial de confirmaciones real (DAG). Si no comprende la diferencia, ¡no utilice esta sintaxis!
Mikko Rantalainen
14
git diff --stat @{2013-11-01}..@{2013-11-30}

o

git diff --stat @{2.weeks.ago}..@{last.week}
AUTOMÓVIL CLUB BRITÁNICO.
fuente
¿Depende esto del reflog? Porque si lo hace, entonces no puede usar esto si el repositorio en el que está ejecutando este comando es más nuevo (es decir, recién clonado) que el historial de confirmaciones que contiene.
2
Sí, esto depende totalmente del reflog. Y sí, esto solo funciona en el historial de copias local, pero es un comando un poco conveniente.
AA.
1
Sí, definitivamente estoy de acuerdo en que es conveniente, siempre que tenga entradas de registro de nuevo lo suficientemente antiguas para admitirlo.
Gracias AA. Usando su respuesta, pude hacer: git annotate --stat .. @ {2017-08-8} filename | menos; git anotar --stat .. @ {5.days.ago} nombre de archivo; para que pueda ver los cambios en contexto.
Chris
Tenga en cuenta que la @{time spec}sintaxis siempre se refiere a su reflog local . No se refiere al historial de confirmaciones real (DAG). Si no comprende la diferencia, ¡no utilice esta sintaxis!
Mikko Rantalainen
4

Quizás

$ git format-patch --committer=<who> --since=yesterday --stdout

es lo que quieres (con o sin '--stdout')?

Jakub Narębski
fuente
1
Pregunta rápida, ¿desde que usa la fecha de confirmación?
CB Bailey
3

Creo que la solución general es usar:

git rev-list -n1 --first-parent --until=<a date string> <a ref>

Sin --first-parent, es posible que obtenga una confirmación de una rama que luego se fusionó a refpero que no se había fusionado a partir de a date string.

Aquí hay una alternativa usando --childreny en greplugar de -n1:

mlm_git_ref_as_of() {
    # # Examples #
    #
    # Show all commits between two dates:
    #
    #     git log $(mlm_git_ref_as_of '2012-05-21 09:00:00-0400')..$(mlm_git_ref_as_of '2012-05-21 17:00:00-0400')
    #
    # Show diffs of all commits between two dates:
    #
    #     git diff $(mlm_git_ref_as_of '2012-05-21 09:00:00-0400')..$(mlm_git_ref_as_of '2012-05-21 17:00:00-0400')
    local as_of="$1"
    local ref="${2:-HEAD}"
    # Get the most recent commit (--children, grep -v ' ') that was on
    # the given branch ($ref, --first-parent) as of a given date
    # ($as_of)
    git rev-list --children --first-parent --until="$as_of" "$ref" | grep -v ' '
}

No estaba familiarizado git whatchangedantes de leer estas preguntas y respuestas, pero me da resultados muy diferentes, por lo que no estoy seguro de lo que está haciendo.

Matt McClure
fuente
3

Otra forma sencilla de obtener una diferencia de todos los cambios desde una fecha determinada es simplemente encontrar la primera confirmación Xque se produjo en esa fecha o después, y luego usar

git diff X

Esto tiene la ventaja de que no depende de las entradas de nuevo registro en un clon nuevo, a diferencia de

git diff <reference>@{n}..
git log <reference>@{n}..

soluciones en

Comunidad
fuente
2

Esta es una respuesta más divertida, porque probablemente haya una mejor manera. Esto mostrará todos los hash de confirmación de hoy.

git log --pretty="format:%H %ai" | grep `date +"%Y-%m-%d"` | awk {'print $1'}`

; ·)

gahooa
fuente
2

También puede usar git-format-patch para preparar parches (diffs) y enviarlos por correo electrónico.

Utilice las opciones [desde] o [rango de revisión] para especificar el rango de confirmaciones.

Nick Dandoulakis
fuente
2

Para ver los cambios de los archivos Git de fecha a fecha en su rama, use la siguiente fórmula:

  1. revisa tu sucursal.
  2. extraer y actualizar cambios desde un repositorio remoto
  3. ver archivos diff desde la fecha hasta el rango de fechas

Fórmula :

git checkout <branch>
git pull
git diff --stat @{fromDate}..@a{toDate}

Preste atención a que las fechas están en formato AAAA-MM-DD :

git diff --stat @{2019-08-20}..@a{2019-08-21}

Si desea observar cambios en un archivo específico en un rango de tiempo específico (ver la diferencia en el código), simplemente navegue por el archivo actual:

Ejemplo :

git diff @{2019-01-01}..@{2019-01-02} ~/dev/myApp/package.json
avivamg
fuente
0

Incluiré la forma en que lo hago: git logpara una fecha, obtendrá valores hash de confirmación para la rama actual. Luego solo uso algo como lo git diff 8fgdfg8..565k4l5que me da la diferencia adecuada agregada por archivos. Espero que esto ayude, aunque no he probado mucho

rostamn739
fuente