Используя Git, как найти изменения между локальным и удаленным

Вот два разных вопроса, но я думаю, что они связаны.

  1. При использовании Git, как мне узнать, какие изменения я зафиксировал локально, но еще не отправил в удаленную ветку? Ищу что-то похожее на команду Mercurial hg outgoing.

  2. При использовании Git, как мне узнать, какие изменения были внесены в удаленную ветку до выполнения извлечения? Ищу что-то похожее на команду Mercurial hg incoming.

Для второго: есть ли способ узнать, что доступно, а затем выбрать изменения, которые я хочу применить?


person ejunker    schedule 23.10.2008    source источник
comment
Глядя на ответы, кажется, что есть некоторая путаница относительно того, что на самом деле делают hg incoming и hg outgoing. Ближайший эквивалент Git, который я нашел, - это опция --dry-run. Просто git pull --dry-run, и вы увидите список всего, что должно произойти.   -  person Roman Starkov    schedule 29.09.2012


Ответы (11)


Git не может отправлять такую ​​информацию по сети, как Hg. Но вы можете запустить git fetch (который больше похож на hg pull, чем на hg fetch) для получения новых коммитов с ваших удаленных серверов.

Итак, если у вас есть ветка с именем master и удаленная ветка с именем origin, после запуска git fetch у вас также должна быть ветка с именем origin/master. Затем вы можете получить git log всех коммитов, которые master должны быть надмножеством origin/master, выполнив git log master..origin/master. Поменяйте местами эти два, чтобы получить противоположное.

Мой друг, Дэвид Доллар, создал пару сценариев оболочки git для имитации hg incoming/outgoing. Вы можете найти их на странице http://github.com/ddollar/git-utils.

person Jordi Bunster    schedule 23.10.2008

Начиная с Git 1.7.0, существует специальный синтаксис, который позволяет вам в общем ссылаться на ветвь восходящего потока: @{u} или @{upstream}.

Чтобы имитировать hg incoming:

git log ..@{u}

Чтобы имитировать hg outgoing:

git log @{u}..

Я использую следующие псевдонимы incoming и outgoing, чтобы упростить использование вышеуказанного:

git config --global alias.incoming '!git remote update -p; git log ..@{u}'
git config --global alias.outgoing 'log @{u}..'
person Richard Hansen    schedule 17.06.2011
comment
git log .. @ {u} выдает мне эти ошибки. (У меня есть как источник, так и исходный репозиторий в моей конфигурации git). ошибка: не найдена ветвь восходящего потока для '' ошибка: ветвь восходящего потока не найдена для '..' ошибка: ветвь восходящего потока не найдена для '..' фатальный: неоднозначный аргумент '.. @ {u}': неизвестная версия или путь отсутствует рабочее дерево. Используйте '-' для отделения путей от ревизий - person Henrik; 01.10.2011
comment
Вы получите эти ошибки, если ваш локальный филиал не настроен с восходящим потоком. Чтобы исправить, запустите git branch --set-upstream foo origin/foo. - person Richard Hansen; 01.10.2011
comment
git log @{u}.. перечисляет для меня каждое изменение в репо. Нет никакого способа, что они еще не существуют. - person Roman Starkov; 28.09.2012
comment
@romkyns: Возможно, ваша локальная ветка имеет неправильную удаленную ветку, настроенную как восходящую. Убедитесь, что git rev-parse --symbolic-full-name @{u} печатает соответствующую удаленную ссылку. Кроме того, git log @{u}.. показывает коммиты, которые недоступны для восходящей ветки, что может включать коммиты, которые уже находятся в удаленном репозитории (если они доступны по другой ссылке). Это произойдет сразу после того, как вы выполните слияние в уже запущенной ветке. - person Richard Hansen; 28.09.2012
comment
@RichardHansen Боюсь, я слишком новичок, чтобы знать, что было бы подходящим для удаленной ссылки, однако это было недавно клонированное репо, на котором я сделал только checkout <somebranch> и merge <otherbranch>. На этом этапе я выполнил log @{u}.. и просмотрел все перечисленные изменения. - person Roman Starkov; 28.09.2012
comment
@romkyns: Если, увидев каждое изменение, вы имеете в виду, что видели все коммиты от <otherbranch>, то это ожидаемо. Поскольку вы только что выполнили слияние, коммиты на <otherbranch> теперь доступны с вашего локального <somebranch>, но еще не доступны с удаленного origin/<somebranch>. Таким образом, эти коммиты отправляются в удаленную ветку origin/<somebranch>. Даже если они не будут новичками в удаленном репозитории, они будут новичками в этой удаленной ветке. - person Richard Hansen; 29.09.2012
comment
@romkyns: Я понимаю, что это сбивает с толку; Git сложно понять. Я настоятельно рекомендую прочитать Pro Git - это поможет вам разобраться в этом материале. - person Richard Hansen; 29.09.2012
comment
Ясно, ваш комментарий проясняет. Мое замешательство связано с тем, что hg outgoing этого не делает. Он просто перечисляет коммиты, которые необходимо отправить в удаленное репо. Я думаю, что git push --dry-run намного ближе по духу к hg outgoing. - person Roman Starkov; 29.09.2012
comment
Вам все равно нужно git fetch все изменения перед выполнением git log ..@{u}, чтобы это сработало. - person anatoly techtonik; 20.02.2013
comment
@anatolytechtonik Действительно. Предлагаемый псевдоним incoming включает git remote update -p, который извлекает изменения. Но я бы предпочел git fetch вместо этого получать изменения только для восходящего потока текущей ветки: git config --global alias.incoming '!git fetch && git log ..@{u}' - person Myk Melez; 25.04.2017

  1. Используйте "git log origin..HEAD"

  2. Используйте «git fetch», а затем «git log HEAD..origin». Вы можете выбрать отдельные коммиты, используя перечисленные идентификаторы коммитов.

Вышеупомянутое, конечно, предполагает, что "origin" - это имя вашей ветки удаленного отслеживания (что и есть, если вы использовали clone с параметрами по умолчанию).

person Greg Hewgill    schedule 23.10.2008
comment
(И если вы не отслеживаете удаленную ветку, это «git log origin / master..HEAD».) - person plindberg; 17.08.2010
comment
origin - это не имя ветки удаленного отслеживания, это имя удаленного. И просто указать удаленное имя не получится, вам нужно указать ветку удаленного отслеживания, которая будет origin / master. - person robinst; 25.05.2011

Также есть это для сравнения всех веток:

git log --branches --not --remotes=origin

Вот что об этом говорится на странице руководства git log:

Показывает все коммиты, которые находятся в любой из локальных веток, но не в какой-либо из ветвей удаленного отслеживания для источника (то, что у вас есть, этого источника нет).

Вышеуказанное относится к outgoing. Для incoming просто поменяйте местами:

git log --remotes=origin --not --branches
person robinst    schedule 25.05.2011

я бы сделал

$ git fetch --dry-run

для hg incoming и

$ git push --dry-run

для hg outgoing.

person chris    schedule 21.01.2014
comment
Извините, я упустил из виду, что это уже было сказано как комментарий к OP. - person chris; 21.01.2014

git-out - это скрипт это имитирует hg outgoing довольно точно. Он анализирует вывод "push -n", поэтому он производит точный вывод, если вам нужно указать дополнительные аргументы для push.

person stepancheg    schedule 05.11.2011

мерзавец входящий

$ git fetch && git log ..origin/master --stat
OR
$ git fetch && git log ..origin/master --patch

мерзавец исходящий

$ git fetch && git log origin/master.. --stat
OR
$ git fetch && git log origin/master.. --patch
person prayagupd    schedule 09.12.2013

Когда ответы «git log» и @ {u} изначально выдавали мне ошибку «неизвестная версия», я попробовал предложить git push --dry-run Крисом / ромкинсом.

Вы получите такой вывод, как «5905..4878 master-> master». 5905 - это последняя фиксация, которая была сделана на удаленном компьютере и была зафиксирована (включая) 4878, которая будет применена к удаленному устройству.

Затем вы можете использовать 5905..4878 в качестве аргументов для нескольких других команд git, чтобы получить более подробную информацию:

git diff 5905..4878 # Gives full code changes in diff style

git log --online 5905..4878 # Displays each commit's comment
person pierce.jason    schedule 07.07.2014

Входящие коммиты по всем веткам можно показать с помощью следующего подхода.

Команда git fetch-diff становится доступной после добавления исполняемого файла с именем git-fetch-diff в ваш PATH, содержащего:

#!/bin/bash

set -e

# get hashes before fetch
old_hashes=$(git log --all --no-color --pretty=format:"%H")

# perform the fetch
git fetch

# get hashes after fetch
new_hashes=$(git log --all --no-color --pretty=format:"%H")

# get the difference
added_hashes=$(comm -1 -3 <(echo "$old_hashes") <(echo "$new_hashes"))

# print added hashes
[ ! -z "$added_hashes" ] && echo "$added_hashes" | git log --stdin --no-walk --oneline

Хэши фиксации сравниваются до и после выборки. Разница возвращается к git log для красивой печати. Внешний вид распечатанного журнала можно дополнительно настроить с помощью таких аргументов, как --pretty=<format> и --graph.

Примечание. Вы можете ограничить время, на которое git log вернется назад во времени, в зависимости от того, сколько переменной bash может храниться в вашей системе, или по соображениям производительности. Это можно сделать, добавив аргумент --max-count=<count>.

person gospes    schedule 08.10.2020

Когда вы выполняете git fetch, все содержимое, включая ветки, теги (refs), временно сохраняется в .git / FETCH_HEAD, содержимое которого можно просмотреть с помощью команды: git log FETCH_HEAD Если вы не используете суффикс -a с git fetch, то по умолчанию , Содержимое FETCH_HEAD будет перезаписано новым содержимым. Из этого содержимого вы можете просмотреть и решить, в какую ветку вы хотите их объединить, если вы это сделаете, или вы можете просто выбрать вишню, если вам нужно только несколько коммитов из того, что было принесено с помощью fetch.

person AMIT PRAKASH PANDEY    schedule 21.10.2015

person    schedule
comment
Сработало у меня (но наоборот) - git diff origin/master master - person Nick Grealy; 01.09.2015