Come posso ottenere la differenza tra tutti i commit avvenuti tra due date con Git?


117

O solo tutti i commit avvenuti tra due date? In SVN, potresti fare qualcosa di simile

svn diff -r{date}:{date}

per farlo! Non riesco a trovare un equivalente Git a questo.

In particolare, sto cercando di scrivere uno script per inviare e-mail quotidiane con tutto il codice commesso quel giorno e da chi.

Risposte:


160

Potresti usare git whatchanged --since="1 day ago" -p

Ci vuole anche una --untildiscussione.

Documenti


Grazie! Era proprio quello che volevo, prende anche il parametro --committer, anche se non è elencato nella sua documentazione! inoltre, "git whatchanged" non appare in "git help"! Non ho idea del perché ... grazie ancora.
Chris,

5
Dovresti rendere questa la tua risposta prescelta in modo che Seth riceva un po 'di karma.
Scott

18
@brbob So che è stata data una risposta molto tempo fa, ma solo per qualcuno che si imbatte in questo (come ho fatto io) Git help 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. Quindi, i documenti incoraggiano l'uso git loginvece di git whatchanged; quest'ultimo comando usa anche l'opzione --no-merge di git log, quindi restituiscono gli stessi risultati.
Ramses

2
git whatchanged è una specie di alias del comando git log secondo il documento di git log
Vincent

2
git whatchangedè deprecato a partire dall'ultima versione corrente 2.21.0. Tutto ciò che è stato git whatchangedraggiunto può essere raggiunto git loged è conservato solo per ragioni storiche. Vedi i dettagli git-scm.com/docs/git-whatchanged/2.21.0
Devy

60

I suggerimenti precedenti presentano alcuni inconvenienti. Fondamentalmente, stavo cercando qualcosa di equivalente a cvs diff -D"1 day ago" -D"2010-02-29 11:11". Raccogliendo sempre più informazioni, ho trovato una soluzione.

Cose che ho provato:

  • git whatchanged --since="1 day ago" -pda qui

    Ma questo dà una differenza per ogni commit, anche se ci sono più commit in un file. So che "appuntamento" è un concetto un po 'sciolto in git , ho pensato che ci doveva essere un modo per farlo.

  • git diff 'master@{1 day ago}..masterdà qualche avvertimento warning: Log for 'master' only goes back to Tue, 16 Mar 2010 14:17:32 +0100.e non mostra tutte le differenze.

  • git format-patch --since=yesterday --stdout non dà niente per me.

  • revs=$(git log --pretty="format:%H" --since="1 day ago");git diff $(echo "$revs"|tail -n1) $(echo "$revs"|head -n1) funziona in qualche modo, ma sembra complicato e non si limita al ramo corrente.

Finalmente:

Stranamente, git-cvsserver non supporta "cvs diff -D" (senza che sia documentato da qualche parte).


4
+1 per git rev-list, che ha fatto molto per risolvere il problema molto simile che stavo vedendo.
me_ e il

Questa non dovrebbe essere la risposta accettata, quella di Seth è più concisa e corretta.
ctford

6
@ctford, a mio avviso, non è corretto. Può segnalare più differenze per un file, non una differenza per file come svn / cvs diff.
Weidenrinde

1
@Weidenrinde +1, questo è molto più intelligente
rostamn739

1
La git diff 'master@{1 day ago}..mastersintassi significa "controlla il reflog e scopri dove il ramo masterpuntava nel tuo repository locale 1 day ago ". In particolare, non utilizzerà la cronologia di commit effettiva del ramo corrente master. Questa è molto raramente la cosa che vuoi veramente.
Mikko Rantalainen

22

"data" è un concetto un po 'sciolto in git. Un commit avrà una data dell'autore che potrebbe essere un bel po 'di tempo nel passato prima che qualcuno effettui il pull / commit del commit nel proprio repository, inoltre il commit potrebbe essere ribasato e aggiornato per essere in cima a un commit apparentemente più recente.

Un commit ha anche una data di commit che viene aggiornata se un commit viene ribasato o modificato in qualsiasi modo. È più probabile che questi commit siano in una sorta di ordine cronologico ma sei ancora in balia del committer che ha l'ora corretta impostata sul suo computer e anche così, un commit non modificato può sedersi su un ramo di funzionalità su un repository remoto indefinitamente prima essere fusa nel ramo principale di un repository centrale.

Ciò che è probabilmente più utile per i tuoi scopi è la data di reflog sul particolare repository in questione. Se hai i reflog per ramo abilitati (vedi git config core.logAllRefUpdates), puoi usare la ref@{date}sintassi per fare riferimento a dove si trovava un ramo in un determinato momento.

Per esempio

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

Puoi anche utilizzare descrizioni "sfocate" come:

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

Questi comandi mostreranno tutti i commit che sono "apparsi" nel ramo dato del repository indipendentemente da quanto siano "vecchi" in base all'autore e alle date di commit.

Nota che il reflog per ramo è specifico di un repository, quindi se stai eseguendo il comando log su un clone e non esegui il pull per (diciamo) un mese, esegui il pull di tutte le modifiche dell'ultimo mese contemporaneamente, quindi tutte le modifiche dell'ultimo mese verranno visualizzate in un @{1 hour ago}..@{now}intervallo. Se sei in grado di eseguire il comando log sul ripostory 'centrale' a cui le persone spingono, allora potrebbe fare quello che vuoi.


Scrittura molto buona e buona risposta alla domanda dichiarata ... ma penso che non aiuterebbe molto a fare ciò che intendeva brbob.
Jakub Narębski

Dipende, potrebbe essere d'aiuto se in realtà desidera analizzare ciò che è stato inviato a un determinato ramo su un determinato repository centrale e il comando log è stato eseguito su quel repository. Penso che sia necessaria una modifica ...
CB Bailey

"data del commit che viene aggiornata se un commit viene ribasato o modificato in qualsiasi modo", in realtà la data non viene mai modificata; l'intero commit viene sostituito con un altro commit (sebbene l'albero potrebbe presumibilmente essere lo stesso).
hasen

2
@hasen j: Tecnicamente hai ragione. I commit sono immutabili. Quando si rebase o si modifica un commit e si crea un nuovo commit, il messaggio di commit esistente, i dettagli dell'autore e la data dell'autore vengono spesso copiati dal vecchio commit, quindi è come se si stesse aggiornando il commit con un nuovo ID commit e data di commit.
CB Bailey

Nota che la @{time spec}sintassi fa sempre riferimento al tuo reflog locale . Non si riferisce alla cronologia effettiva del commit (DAG). Se non sottovaluti la differenza, non utilizzare questa sintassi!
Mikko Rantalainen

14
git diff --stat @{2013-11-01}..@{2013-11-30}

o

git diff --stat @{2.weeks.ago}..@{last.week}

Questo dipende dal reflog? Perché se lo fa, allora non puoi effettivamente usarlo se il repo in cui stai eseguendo questo comando è più recente (cioè appena clonato) rispetto alla cronologia di commit che contiene.

2
Sì, questo dipende totalmente dal reflog. E sì, funziona solo nella cronologia delle copie locale, ma è un piccolo comando conveniente.
AA.

1
Sì, sono assolutamente d'accordo sul fatto che sia conveniente, a patto che tu abbia voci di reflog abbastanza vecchie da supportarlo.

Grazie AA. Usando la tua risposta, sono stato in grado di fare: git annotate --stat .. @ {2017-08-8} filename | less; git annotate --stat .. @ {5.days.ago} nomefile; così posso vedere i cambiamenti nel contesto.
Chris

Nota che la @{time spec}sintassi fa sempre riferimento al tuo reflog locale . Non si riferisce alla cronologia effettiva del commit (DAG). Se non sottovaluti la differenza, non utilizzare questa sintassi!
Mikko Rantalainen

4

Forse

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

è quello che vuoi (con o senza '--stdout')?


1
Domanda veloce, dal momento che usa la data di commit?
CB Bailey

3

Credo che la soluzione generale sia usare:

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

Senza --first-parent, potresti ottenere un commit da un ramo che è stato successivamente unito a refma che non era stato unito a date string.

Ecco un'alternativa che utilizza --childrene grepinvece di -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 ' '
}

Non avevo familiarità con git whatchangedprima di leggere questa domanda e risposta, ma dà risultati molto diversi per me, quindi non sono sicuro di cosa stia facendo.


3

Un altro modo semplice per ottenere una differenza di tutte le modifiche poiché una certa data è semplicemente trovare il primo commit Xche si è verificato in o dopo quella data, quindi utilizzare

git diff X

Questo ha il vantaggio di non dipendere dalle voci di reflog in un nuovo clone, a differenza del

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

soluzioni in


3

Per vedere le modifiche dei file Git dalla data alla data sul tuo ramo, usa la seguente formula:

  1. controlla la tua filiale.
  2. estrarre e aggiornare le modifiche dal repository remoto
  3. guarda i file diff dalla data all'intervallo di date

Formula :

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

Fai attenzione che le date siano nel formato AAAA-MM-GG :

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

Se desideri osservare le modifiche su un file specifico in un intervallo di tempo specifico (guarda diff nel codice), naviga nel file corrente:

Esempio :

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

2

Questa è una risposta più divertente, perché probabilmente c'è un modo migliore. Questo mostrerà tutti gli hash di commit per oggi.

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

; ·)


2

Puoi anche usare git-format-patch per preparare patch (diff) e inviarle tramite e-mail.

Usa le opzioni [da] o [intervallo di revisione] per specificare l'intervallo di commit.


0

Ti metto nel modo in cui lo faccio: git logper una data ti dà gli hash di commit per il ramo corrente. Quindi uso qualcosa di simile git diff 8fgdfg8..565k4l5che mi dà la giusta differenza aggregata per file. Spero che questo aiuti, ma non testato molto

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.