Как я могу получить разницу между всеми коммитами, которые произошли между двумя датами с Git? - PullRequest
107 голосов
/ 22 июля 2009

Или просто все коммиты, которые произошли между двумя датами? В SVN вы можете сделать что-то вроде

svn diff -r{date}:{date}

чтобы сделать это! Я не могу найти Git, эквивалентный этому.

В частности, я рассматриваю написание сценария для ежедневной рассылки электронных писем со всем кодом, совершенным в тот день и кем.

Ответы [ 10 ]

151 голосов
/ 22 июля 2009

Вы можете использовать git whatchanged --since="1 day ago" -p

Также требуется аргумент --until.

Docs

56 голосов
/ 16 марта 2010

Предыдущие предложения имеют некоторые недостатки. По сути, я искал что-то эквивалентное cvs diff -D"1 day ago" -D"2010-02-29 11:11". Собирая все больше и больше информации, я нашел решение.

Вещи, которые я пробовал:

  • git whatchanged --since="1 day ago" -p от здесь

    Но это дает разницу для каждого коммита, даже если в одном файле несколько коммитов. Я знаю, что "date" - это немного не совсем понятное понятие в git , я подумал, что должен быть какой-то способ сделать это.

  • git diff 'master@{1 day ago}..master выдает предупреждение warning: Log for 'master' only goes back to Tue, 16 Mar 2010 14:17:32 +0100. и отображает не все различия.

  • git format-patch --since=yesterday --stdout мне ничего не дает.

  • revs=$(git log --pretty="format:%H" --since="1 day ago");git diff $(echo "$revs"|tail -n1) $(echo "$revs"|head -n1) работает как-то, но кажется сложным и не ограничивается текущей ветвью.

Наконец:

Как ни странно, git-cvsserver не поддерживает "cvs diff -D" (без этого это где-то задокументировано).

21 голосов
/ 22 июля 2009

«дата» - это немного странная концепция в git. У коммита будет дата автора, которая может пройти довольно давно, прежде чем кто-то на самом деле извлечет / зафиксирует коммит в своем репозитории, также коммит может быть перебазирован и обновлен, чтобы быть поверх явно нового коммита.

У коммита также есть дата коммита, которая обновляется, если коммит перебазирован или изменен каким-либо образом. Скорее всего, эти коммиты будут в каком-то хронологическом порядке, но вы все еще находитесь во власти коммиттера, у которого на компьютере установлено правильное время, и даже в этом случае неизмененный коммит может находиться в ветви функций в удаленном репозитории бесконечно долго объединяется с основной ветвью центрального хранилища.

Что, вероятно, наиболее полезно для ваших целей, это дата reflog для конкретного репозитория. Если у вас включены повторные журналы для каждой ветви (см. git config core.logAllRefUpdates), то вы можете использовать синтаксис ref@{date}, чтобы указать, где была ветвь в определенное время.

1009 * Е.Г. *

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

Вы также можете использовать «нечеткие» описания, такие как:

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

Эти команды покажут все коммиты, которые «появились» в данной ветке хранилища, независимо от того, насколько «старыми» они являются в соответствии с их автором и датами коммитов.

Обратите внимание, что reflog для каждой ветви специфичен для репозитория, поэтому, если вы запускаете команду log на клоне и не тянете (скажем) месяц, то извлекаете все изменения за последний месяц сразу все изменения за последний месяц появятся в диапазоне @{1 hour ago}..@{now}. Если вы можете запустить команду log в «центральном» репозитории, куда люди отправляют файлы, тогда он может делать то, что вы хотите.

14 голосов
/ 24 ноября 2013
git diff --stat @{2013-11-01}..@{2013-11-30}

или

git diff --stat @{2.weeks.ago}..@{last.week}
4 голосов
/ 22 июля 2009

Возможно

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

это то, что вы хотите (с или без '--stdout')?

3 голосов
/ 22 июля 2014

Другой простой способ получения различий всех изменений с определенной даты - просто найти первый коммит X, произошедший в эту дату или после этой даты, а затем использовать

git diff X

Это имеет то преимущество, что не зависит от записей reflog в новом клоне, в отличие от

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

решений в

3 голосов
/ 22 мая 2012

Я считаю, что общее решение заключается в использовании:

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

Без --first-parent вы можете получить коммит из ветви, которая позже была объединена в a ref, но не была объединена с a date string.

Вот альтернативный вариант использования --children и grep вместо -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 ' '
}

Я не был знаком с git whatchanged до прочтения этих вопросов и ответов, но это дает мне совсем другие результаты, поэтому я не уверен, что он делает.

2 голосов
/ 22 июля 2009

Вы также можете использовать git-format-patch для подготовки исправлений (различий) и отправки их по электронной почте.

Используйте опции [с] или [диапазон редакций], чтобы указать диапазон фиксации.

2 голосов
/ 22 июля 2009

Это более забавный ответ, потому что, вероятно, есть лучший способ. Это покажет все хэши на сегодня.

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

; & Мидот;)

0 голосов
/ 16 июня 2016

Я добавлю, как я это делаю: git log для даты дает вам зафиксировать хэши для текущей ветви. Тогда я просто использую что-то вроде git diff 8fgdfg8..565k4l5, что дает мне правильную разницу, агрегированную по файлам. Надеюсь, что это помогает, не очень проверено, хотя

...