Bagaimana saya bisa mendapatkan perbedaan antara semua komit yang terjadi antara dua tanggal dengan Git?

117

Atau hanya semua komitmen yang terjadi antara dua tanggal? Di SVN, Anda bisa melakukan sesuatu seperti

svn diff -r{date}:{date}

untuk melakukannya! Sepertinya saya tidak dapat menemukan Git yang setara dengan ini.

Secara khusus, saya sedang menulis skrip untuk mengirimkan email harian dengan semua kode yang dilakukan hari itu dan oleh siapa.

Chris
sumber

Jawaban:

160

Anda bisa menggunakan git whatchanged --since="1 day ago" -p

Ini juga membutuhkan --untilargumen.

Docs

seth
sumber
Terima kasih! Ini benar apa yang saya inginkan, bahkan mengambil parameter --committer, meskipun itu tidak tercantum dalam dokumentasinya! juga, 'git whatchanged' tidak muncul di 'git help'! Tidak tahu kenapa ... terima kasih lagi.
Chris
5
Anda harus menjadikan ini jawaban pilihan Anda sehingga seth mendapat karma.
Scott
18
@brbob Saya tahu ini telah dijawab sejak lama, tetapi hanya untuk seseorang yang tersandung pada ini (seperti yang saya lakukan) bantuan Git mengatakan: 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. Jadi, dokumen mendorong penggunaan git logalih-alih git whatchanged; perintah terakhir ini juga menggunakan opsi --no-merge dari git log, jadi mereka mengeluarkan hasil yang sama.
Ramses
2
git whatchanged adalah jenis alias dari perintah git log menurut dokumen git log
Vincent
2
git whatchangedtidak digunakan lagi sejak versi terbaru 2.21.0. Semua yang git whatchangeddicapai dapat dicapai oleh git logdan itu hanya dipertahankan karena alasan sejarah. Lihat detil git-scm.com/docs/git-whatchanged/2.21.0
Devy
60

Saran sebelumnya memiliki beberapa kekurangan. Pada dasarnya, saya mencari sesuatu yang setara dengan cvs diff -D"1 day ago" -D"2010-02-29 11:11". Saat mengumpulkan lebih banyak informasi, saya menemukan solusi.

Hal yang telah saya coba:

  • git whatchanged --since="1 day ago" -pdari sini

    Tapi ini memberikan perbedaan untuk setiap komit, meskipun ada beberapa komit dalam satu file. Saya tahu bahwa "kencan" adalah konsep yang agak longgar , saya pikir pasti ada cara untuk melakukan ini.

  • git diff 'master@{1 day ago}..mastermemberikan beberapa peringatan warning: Log for 'master' only goes back to Tue, 16 Mar 2010 14:17:32 +0100.dan tidak menampilkan semua diff.

  • git format-patch --since=yesterday --stdout tidak memberikan apapun untukku

  • revs=$(git log --pretty="format:%H" --since="1 day ago");git diff $(echo "$revs"|tail -n1) $(echo "$revs"|head -n1) bekerja entah bagaimana, tetapi tampaknya rumit dan tidak terbatas pada cabang saat ini.

Akhirnya:

Lucunya, git-cvsserver tidak mendukung "cvs diff -D" (tanpanya, ini didokumentasikan di suatu tempat).

Weidenrinde
sumber
4
1 untuk git rev-list, yang sangat membantu dalam memecahkan masalah yang sangat mirip yang saya lihat.
me_and
Ini seharusnya bukan jawaban yang diterima, seth lebih ringkas dan tepat.
ctford
6
@ cctford, menurut saya, itu tidak benar. Ini mungkin melaporkan beberapa perbedaan untuk satu file, bukan satu perbedaan per file sebagai svn / cvs diff.
Weidenrinde
1
@Weidenrinde +1, ini jauh lebih pintar
rostamn739
1
The git diff 'master@{1 day ago}..mastersintaks berarti "cek yang reflog dan mencari tahu di mana cabang masterdigunakan untuk titik dalam repositori lokal Anda 1 day ago ". Secara khusus, tidak akan menggunakan sejarah komit aktual dari cabang saat ini master. Ini sangat jarang hal yang benar-benar Anda inginkan.
Mikko Rantalainen
22

"date" adalah konsep yang agak longgar di git. Sebuah komit akan memiliki tanggal pembuat yang mungkin beberapa waktu di masa lalu sebelum seseorang benar-benar menarik / melakukan komit ke dalam repositori mereka, juga komit mungkin di-rebased dan diperbarui untuk berada di atas komit yang tampaknya lebih baru.

Komit juga memiliki tanggal komit yang diperbarui jika komit di-rebased atau diubah dengan cara apa pun. Komit ini lebih cenderung berada dalam semacam urutan kronologis tetapi Anda masih bergantung pada pengatur waktu yang memiliki waktu yang tepat yang disetel di komputernya dan meskipun demikian, komit yang tidak dimodifikasi dapat duduk di cabang fitur pada repositori jarak jauh tanpa batas waktu sebelumnya digabung ke dalam cabang master dari repositori pusat.

Apa yang mungkin paling berguna untuk tujuan Anda adalah tanggal reflog pada repositori tertentu yang dimaksud. Jika Anda mengaktifkan reflog per cabang (lihat git config core.logAllRefUpdates), Anda dapat menggunakan ref@{date}sintaks untuk merujuk ke lokasi cabang pada waktu tertentu.

Misalnya

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

Anda juga dapat menggunakan deskripsi 'kabur' seperti:

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

Perintah-perintah ini akan menampilkan semua komit yang telah 'muncul' di cabang tertentu dari repositori terlepas dari seberapa 'tua' mereka sebenarnya menurut pembuat dan tanggal komitnya.

Perhatikan bahwa reflog per cabang khusus untuk repositori, jadi jika Anda menjalankan perintah log pada klon, dan Anda tidak menarik (katakanlah) sebulan, maka tarik semua perubahan untuk bulan terakhir sekaligus, maka semua perubahan bulan lalu akan muncul dalam sebuah @{1 hour ago}..@{now}rentang. Jika Anda dapat menjalankan perintah log di repostori 'sentral' yang didorong orang, maka perintah tersebut dapat melakukan apa yang Anda inginkan.

CB Bailey
sumber
Tulisan yang sangat bagus dan jawaban yang bagus untuk pertanyaan yang dinyatakan ... tapi saya pikir itu tidak akan banyak membantu dengan melakukan apa yang diinginkan brbob.
Jakub Narębski
Itu tergantung, mungkin membantu jika dia benar-benar ingin mengurai apa yang didorong ke cabang tertentu pada repositori pusat tertentu dan perintah log dijalankan pada repositori itu. Saya pikir ada pengeditan dalam urutan ...
CB Bailey
"tanggal komit yang diperbarui jika komit di-rebased atau diubah dengan cara apapun", sebenarnya tanggal tidak pernah berubah; seluruh komit akan diganti dengan komit lain (meskipun pohonnya bisa jadi sama).
hasen
2
@hasen j: Secara teknis, Anda benar. Komitmen tidak bisa diubah. Ketika Anda mendasarkan kembali atau mengubah komit dan membuat komit baru, pesan komit yang ada, detail penulis dan tanggal penulis sering disalin dari komit lama sehingga seperti Anda memperbarui komit dengan id komit baru dan tanggal komit.
CB Bailey
Perhatikan bahwa @{time spec}sintaks selalu mengacu pada reflog lokal Anda . Ini tidak mengacu pada riwayat komit aktual (DAG). Jika Anda tidak memahami perbedaannya, jangan gunakan sintaks ini!
Mikko Rantalainen
14
git diff --stat @{2013-11-01}..@{2013-11-30}

atau

git diff --stat @{2.weeks.ago}..@{last.week}
A A.
sumber
Apakah ini tergantung pada reflognya? Karena jika ya, maka Anda tidak dapat benar-benar menggunakan ini jika repo tempat Anda menjalankan perintah ini lebih baru (yaitu baru saja dikloning) daripada riwayat komit yang dikandungnya.
2
Ya, ini sepenuhnya bergantung pada reflognya. Dan ya, ini hanya berfungsi di riwayat penyalinan lokal, tetapi merupakan perintah yang mudah digunakan.
AA.
1
Ya, saya sangat setuju bahwa ini nyaman, selama Anda memiliki entri reflog yang cukup tua untuk mendukungnya.
Terima kasih AA. Menggunakan jawaban Anda, saya dapat melakukan: git annotate --stat .. @ {2017-08-8} nama file | kurang; git annotate --stat .. @ {5.days.ago} nama file; jadi saya bisa melihat perubahan konteks.
Chris
Perhatikan bahwa @{time spec}sintaks selalu mengacu pada reflog lokal Anda . Ini tidak mengacu pada riwayat komit aktual (DAG). Jika Anda tidak memahami perbedaannya, jangan gunakan sintaks ini!
Mikko Rantalainen
4

Mungkin

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

apa yang kamu inginkan (dengan atau tanpa '--stdout')?

Jakub Narębski
sumber
1
Pertanyaan singkat, apakah --sejak menggunakan tanggal komit?
CB Bailey
3

Saya yakin solusi umumnya adalah menggunakan:

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

Tanpa --first-parent, Anda mungkin mendapatkan komit dari cabang yang kemudian digabungkan menjadi a reftetapi belum digabungkan sejak a date string.

Berikut alternatif penggunaan --childrendan grepalih-alih -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 ' '
}

Saya tidak terbiasa git whatchangedsebelum membaca T&J ini, tetapi memberikan hasil yang sangat berbeda untuk saya, jadi saya tidak yakin apa yang dilakukannya.

Matt McClure
sumber
3

Cara sederhana lain yang Anda bisa mendapatkan perbedaan dari semua perubahan sejak tanggal tertentu adalah dengan menemukan komit pertama Xyang terjadi pada atau setelah tanggal itu, lalu gunakan

git diff X

Ini memiliki keuntungan karena tidak bergantung pada entri reflog dalam klon baru, tidak seperti

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

solusi dalam

Komunitas
sumber
3

Untuk melihat file Git berubah dari tanggal ke tanggal di cabang Anda, gunakan rumus berikut:

  1. checkout cabang Anda.
  2. tarik dan perbarui perubahan dari repositori jarak jauh
  3. perhatikan file diff dari rentang tanggal ke tanggal

Rumus :

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

Perhatikan bahwa tanggalnya menggunakan format YYYY-MM-DD :

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

Jika Anda ingin mengamati perubahan pada file tertentu dalam rentang waktu tertentu (perhatikan perbedaan dalam kode), cukup buka file saat ini:

Contoh :

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

Ini lebih merupakan jawaban yang lucu, karena kemungkinan ada cara yang lebih baik. Ini akan menampilkan semua hash komit untuk hari ini.

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

; ·)

gahooa
sumber
2

Anda juga dapat menggunakan git-format-patch untuk menyiapkan patch (diffs) dan mengirimkannya melalui email.

Gunakan opsi [karena] atau [rentang revisi] untuk menentukan rentang komit.

Nick Dandoulakis
sumber
0

Saya akan memberikan cara saya melakukannya: git loguntuk tanggal memberi Anda melakukan hash untuk cabang saat ini. Lalu saya hanya menggunakan sesuatu seperti git diff 8fgdfg8..565k4l5yang memberi saya perbedaan yang tepat dikumpulkan oleh file. Semoga ini bisa membantu, meskipun tidak banyak diuji

rostamn739
sumber