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

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

svn diff -r{date}:{date}

сделать это! Кажется, я не могу найти Git, эквивалентный этому.

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


person Chris    schedule 21.07.2009    source источник


Ответы (11)


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

Он также принимает аргумент --until.

Документы

person seth    schedule 21.07.2009
comment
Спасибо! Это было именно то, что я хотел, он даже принимает параметр --committer, хотя это не указано в его документации! кроме того, «git whatchanged» не отображался в «git help»! Не знаю, почему... еще раз спасибо. - person Chris; 22.07.2009
comment
Вы должны выбрать этот ответ, чтобы Сет получил некоторую карму. - person Scott; 22.07.2009
comment
Чувак, какой удар по яйцам для Сета - person gtd; 15.08.2009
comment
Используйте этот ответ, если вы предпочитаете несколько различий в файле. - person Greg M. Krsak; 22.04.2014
comment
@brbob Я знаю, что на этот вопрос уже давно был дан ответ, но только для тех, кто наткнется на это (как и я), справка Git говорит: 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. Итак, документы рекомендуют использовать git log вместо git whatchanged; эта последняя команда также использует параметр --no-merge журнала git, поэтому они выводят те же результаты. - person Ramses; 29.07.2014
comment
git whatchanged — это своего рода псевдоним команды git log согласно документу git log - person Vincent; 15.03.2015
comment
git whatchanged устарела с текущей последней версии 2.21.0. Все достигнутое git whatchanged может быть достигнуто с помощью git log, и это сохраняется только по историческим причинам. Подробнее см. git-scm.com/docs/git-whatchanged/2.21.0< /а> - person Devy; 21.05.2019

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

Что я пробовал:

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

    Но это дает разницу для каждого коммита, даже если в одном файле несколько коммитов. Я знаю, что "дата" - это немного расплывчатое понятие в 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" (хотя это где-то задокументировано).

person Weidenrinde    schedule 16.03.2010
comment
+1 за git rev-list, который во многом помог решить очень похожую проблему, с которой я сталкивался. - person me_and; 15.09.2011
comment
Это не должен быть принятый ответ, ответ Сета более краток и правилен. - person ctford; 30.01.2014
comment
@ctford, на мой взгляд, это неправильно. Он может сообщать о нескольких различиях для одного файла, а не об одном различии на файл, как svn/cvs diff. - person Weidenrinde; 19.02.2014
comment
@Weidenrinde +1, это намного умнее - person rostamn739; 16.06.2016
comment
Синтаксис git diff 'master@{1 day ago}..master означает проверку журнала ссылок и выяснение того, где ветвь master раньше указывала в вашем локальном репозитории 1 day ago. В частности, не будет использоваться фактическая история коммитов текущей ветки master. Это очень редко то, чего вы действительно хотите. - person Mikko Rantalainen; 27.06.2018
comment
Чтобы получить изменения за текущий день, используйте --before="midnight" - person Tomáš Hübelbauer; 16.03.2021

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

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

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

E.g.

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

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

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

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

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

person CB Bailey    schedule 21.07.2009
comment
Очень хорошая рецензия и хороший ответ на заданный вопрос... но я думаю, что это мало поможет в выполнении того, что задумал brbob. - person Jakub Narębski; 22.07.2009
comment
Это зависит от того, может ли это помочь, если он действительно хочет проанализировать то, что было отправлено в определенную ветку в определенном центральном репозитории, и команда журнала была запущена в этом репозитории. Я думаю, что редактирование в порядке ... - person CB Bailey; 22.07.2009
comment
дата фиксации, которая обновляется, если фиксация перебазируется или изменяется каким-либо образом, на самом деле дата никогда не меняется; вся фиксация заменяется другой фиксацией (хотя дерево предположительно может быть таким же). - person hasen; 16.03.2010
comment
@hasen j: Технически ты прав. Коммиты неизменяемы. Когда вы переустанавливаете или изменяете фиксацию и создаете новую фиксацию, существующее сообщение фиксации, сведения об авторе и дата автора часто копируются из старой фиксации, поэтому как вы обновляете фиксацию новой фиксацией. идентификатор и дата фиксации. - person CB Bailey; 16.03.2010
comment
Обратите внимание, что синтаксис @{time spec} всегда ссылается на ваш локальный журнал ссылок. Это не относится к фактической истории коммитов (DAG). Если вы не понимаете разницы, не используйте этот синтаксис! - person Mikko Rantalainen; 27.06.2018

Возможно

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

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

person Jakub Narębski    schedule 21.07.2009
comment
Быстрый вопрос, --since использует дату коммита? - person CB Bailey; 22.07.2009

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

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 до того, как прочитал эти вопросы и ответы, но для меня это дает совсем другие результаты, поэтому я не уверен, что он делает.

person Matt McClure    schedule 21.05.2012

Еще один простой способ получить разницу всех изменений с определенной даты — просто найти первую фиксацию X, которая произошла в эту дату или позже, а затем использовать

git diff X

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

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

решения в

person Community    schedule 22.07.2014

Чтобы отслеживать изменения файлов Git от даты к дате в вашей ветке, используйте следующую формулу:

  1. проверьте свою ветку.
  2. извлекать и обновлять изменения из удаленного репозитория
  3. смотреть diff файлы от даты до диапазона дат

Формула:

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

Обратите внимание, что даты указаны в формате ГГГГ-ММ-ДД:

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

Если вы хотите наблюдать за изменениями в конкретном файле за определенный период времени (просматривать различия в коде), просто перейдите к текущему файлу:

Пример:

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

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

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

;)

person gahooa    schedule 21.07.2009

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

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

person Nick Dandoulakis    schedule 21.07.2009

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

person rostamn739    schedule 16.06.2016

person    schedule
comment
Это зависит от рефлога? Потому что, если это так, вы не можете использовать это, если репо, в котором вы запускаете эту команду, новее (т.е. недавно клонировано), чем история коммитов, которую оно содержит. - person ; 22.07.2014
comment
Да, это полностью зависит от reflog. И да, это работает только в локальной истории копирования, но это немного удобная команда. - person AA.; 22.07.2014
comment
Да, я определенно согласен с тем, что это удобно, если у вас есть достаточно старые записи reflog, чтобы его поддерживать. - person ; 22.07.2014
comment
Спасибо АА. Используя ваш ответ, я смог сделать: git annotate --stat ..@{2017-08-8} имя файла | less;git annotate --stat ..@{5.days.ago} имя файла; так что я могу видеть изменения в контексте. - person Chris; 14.09.2017
comment
Обратите внимание, что синтаксис @{time spec} всегда ссылается на ваш локальный журнал ссылок. Это не относится к фактической истории коммитов (DAG). Если вы не понимаете разницы, не используйте этот синтаксис! - person Mikko Rantalainen; 27.06.2018
comment
ИМО, это более подходящий ответ на вопрос. - person mask; 12.09.2018