Як я можу отримати різницю між усіма послугами, які відбулися між двома датами з Git?


116

Або просто всі зобов’язання, які відбулися між двома датами? У SVN ви могли зробити щось подібне

svn diff -r{date}:{date}

зробити це! Я не можу знайти Git, аналогічний цьому.

Зокрема, я дивлюся на написання сценарію, щоб надсилати щоденні електронні листи із усім кодом, зробленим у той день, і ким.

Відповіді:


159

Ви можете використовувати git whatchanged --since="1 day ago" -p

Це також бере --untilаргументи.

Документи


Дякую! Це було саме те, що я хотів, він навіть приймає параметр - committer, хоча це не вказано в його документації! також "git whatchanged" не відображається в "git help"! Не знаю, чому ... ще раз дякую.
Кріс

5
Ви повинні зробити це обраною вами відповіддю, щоб сет отримав певну карму.
Скотт

18
@brbob Я знаю, що на це відповіли давно, але лише для того, хто натрапляє на це (як я це зробив) Git help каже: 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, тому вони виводять однакові результати.
Рамзес

2
git whatchanged - це своєрідний псевдонім команди git log згідно з документом git log
Vincent

2
git whatchangedзастаріла, оскільки поточна остання версія 2.21.0. Все git whatchangedдосягнуте може бути досягнуто git logі збережене лише з історичних причин. Детальніше git-scm.com/docs/git-whatchanged/2.21.0
DEVY

60

Попередні пропозиції мають деякі недоліки. В основному я шукав щось рівнозначне 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" (без цього він десь задокументований).


4
+1 для git rev-list, який пройшов довгий шлях до вирішення дуже подібної проблеми, яку я бачив.
me_and

Це не повинно бути прийнятою відповіддю, Seth є більш стислим і правильним.
ctford

6
@ctford, на мій погляд, це не правильно. Він може повідомляти про кілька розрізнів для одного файлу, а не один розл на файл, як svn / cvs diff.
Вайденрінде

1
@Weidenrinde +1, це набагато розумніше
rostamn739

1
В git diff 'master@{1 day ago}..masterкошти синтаксису «перевірити на reflog і з'ясувати , де гілка masterвикористовується для точки в локальному сховищі 1 day ago ». Зокрема, не буде використана фактична історія фіксування поточної гілки master. Це дуже рідко те, що ти дуже хочеш.
Мікко Ранталайнен

22

"дата" - це трохи розгублене поняття в git. Комісія матиме авторську дату, яка може зайняти деякий час у минулому, перш ніж хтось насправді перетягне / здійснить зобов’язання у своє сховище, також зобов’язання може бути переоформлено та оновлено таким чином, щоб воно було зверху, мабуть, більш новим.

Комісія також має дату зобов’язань, яка оновлюється, якщо зобов’язання перезавантажується чи змінюється будь-яким чином. Ці коміти, швидше за все, мають певний хронологічний порядок, але ви все ще на волі того, хто виконує правильний час, встановлений на своєму комп’ютері, і навіть так, немодифікована фіксація може сидіти на гілці функцій у віддаленому сховищі на невизначений час раніше об'єднуючись у головну гілку центрального сховища.

Що, мабуть, найкорисніше для ваших цілей - це дата перегляду конкретного сховища. Якщо увімкнено відгалуження для кожної гілки (див. git config core.logAllRefUpdates), Ви можете використовувати ref@{date}синтаксис для позначення того, де в певний час була гілка.

Напр

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

Ви також можете використовувати "нечіткі" описи, такі як:

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

Ці команди покажуть усі комітети, які "з'явилися" в даній гілці сховища, незалежно від того, наскільки вони "старі", відповідно до їх автора та дати фіксації.

Зауважте, що рефлог на галузь характерний для сховища, тож якщо ви виконуєте команду журналу на клоні, і ви не тягнете (скажімо) місяць, тоді витягніть всі зміни за останній місяць одразу, то всі зміни за останній місяць з’являться в @{1 hour ago}..@{now}діапазоні. Якщо вам вдасться запустити команду журналу на «центральній» репосторії, до якої підштовхуються люди, то вона може робити все, що ви хочете.


Дуже гарна написання та хороша відповідь на поставлене запитання ... але я думаю, що це не дуже допоможе зробити те, що задумав brbob.
Якуб Нарубський

Це залежить, це може допомогти, якщо він насправді хоче проаналізувати те, що було висунуто до певної гілки в певному центральному сховищі, і команда журналу виконувалася в цьому сховищі. Я думаю, що редагування в порядку ...
CB Bailey

"дата фіксації, яка оновлюється, якщо зобов'язання перезавантажується чи змінюється будь-яким чином", фактично дата ніколи не змінюється; весь комітет заміняється на інший коміт (хоча, мовляв, дерево могло б бути таким самим).
hasen

2
@hasen j: Технічно ви маєте рацію. Коміти незмінні. Коли ви перезаписуєте або змінюєте комісію та створюєте нове зобов’язання, існуюче повідомлення про вчинення, деталі автора та дата автора часто копіюються зі старої фіксації, так що це так, як ви оновлюєте комісію новим ідентифікатором чи датою виконання.
CB Bailey

Зауважте, що @{time spec}синтаксис завжди посилається на ваш локальний рефлог . Він не стосується фактичної історії комісій (DAG). Якщо ви не розумієте різниці, не використовуйте цей синтаксис!
Мікко Ранталайнен

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

або

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

Це залежить від рефлогу? Тому що, якщо це так, то ви фактично не можете використовувати це, якщо репо, в якому ви виконуєте цю команду, є новішим (тобто щойно клонованим), ніж історія фіксованих файлів, яку вона містить.

2
Так, це повністю залежить від рефлогу. І так, це працює лише в локальній історії копіювання, але є трохи зручною командою.
АА.

1
Так, я безумовно погоджуюсь, що це зручно, якщо у вас є записи про відкладення, які є досить старими, щоб їх підтримати.

Дякую А.А. Використовуючи вашу відповідь, я зміг зробити: git annotate --stat .. @ {2017-08-8} ім'я файлу | менше; git annotate --stat .. @ {5.days.ago} ім'я файлу; тож я бачу зміни в контексті.
Кріс

Зауважте, що @{time spec}синтаксис завжди посилається на ваш локальний рефлог . Він не стосується фактичної історії комісій (DAG). Якщо ви не розумієте різниці, не використовуйте цей синтаксис!
Мікко Ранталайнен

4

Можливо,

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

це те, що ви хочете (з або без '--stdout')?


1
Швидке запитання, чи - оскільки використовує дату фіксації?
CB Bailey

3

Я вважаю, що загальним рішенням є використання:

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

Без - першого батька, ви можете отримати комісію від гілки, яка згодом була об'єднана, 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тим, як читати це запитання, але це дає дуже різні результати для мене, тому я не впевнений, що це робить.


3

Ще один простий спосіб, за яким ви можете отримати різні зміни, оскільки певна дата - це просто знайти перше зобов’язання, Xяке відбулося на дату або після цієї дати, а потім використовувати

git diff X

Це має ту перевагу, що це не залежить від записів релогів у свіжому клоні, на відміну від

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

рішення в


2

Це скоріше смішна відповідь, адже, ймовірно, є кращий спосіб. Це покаже всі хеши для фіксації на сьогодні.

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

; ·)


2

Ви також можете використовувати git-format-patch для підготовки патчів (відмінностей) та надсилання їх електронною поштою.

Використовуйте параметри [з моменту] або [діапазон редагування] для визначення діапазону комісій.


2

Для того, щоб спостерігати за зміною файлів Git від дати до дати у вашій філії, використовуйте наступну формулу:

  1. оформити свою філію.
  2. витягніть та оновіть зміни з віддаленого сховища
  3. дивіться різні файли від дати до діапазону дат

Формула :

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

Зверніть увагу, що дати у форматі РРРР-ММ-DD :

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

Якщо ви хочете спостерігати за змінами у певному файлі за певний часовий діапазон (дивіться різний код), просто перейдіть до поточного файлу:

Приклад :

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

0

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.