Git виноват предыдущие коммиты?

Можно ли увидеть, кто редактировал конкретную строку до фиксации, о которой сообщил git blame, например, историю коммитов для данной строки?

Например, я запускаю следующее (в превосходном проекте uncrustify):

$ git blame -L10,+1 src/options.cpp
^fe25b6d (Ben Gardner 2009-10-17 13:13:55 -0500 10) #include "prototypes.h"

Как я могу узнать, кто редактировал эту строку до фиксации fe25b6d? И кто редактировал это перед этим коммитом?


person Sedate Alien    schedule 23.02.2011    source источник
comment
если причина, по которой вы ищете предыдущие коммиты, - это изменения пробелов, используйте параметр -w. Также есть -M для перемещенного / скопированного кода   -  person brita_    schedule 16.06.2014
comment
Чтобы найти все коммиты, в которых используется данное слово, см. мой скрипт ниже   -  person VonC    schedule 11.07.2014
comment
Вот полезный скрипт для добавления этой функции на github greasyfork .org / en / scripts /   -  person Aaron Hoffman    schedule 14.12.2015
comment
Не уверен, как выглядел github после публикации @AaronHoffman, но это намного проще виноват - и получить обвинение в предыдущих версиях - теперь в github.   -  person ruffin    schedule 12.09.2017


Ответы (14)


git blame -L 10,+1 fe25b6d^ -- src/options.cpp

Вы можете указать версию для git blame, с которой нужно начинать поиск (вместо значения по умолчанию HEAD); fe25b6d^ является родительским элементом fe25b6d.


Изменить: впервые в Git 2.23 у нас есть --ignore-rev опция добавлена ​​в git blame:

git blame --ignore-rev fe25b6d

Хотя это не отвечает на вопрос OP о предоставлении стека коммитов (для этого вы будете использовать git log, в соответствии с другим ответом), это лучший способ этого решения, поскольку вы потенциально не ошибетесь в других строках.

person Amber    schedule 23.02.2011
comment
Можете ли вы получить полную историю без повторного ввода команды несколько раз с разными хешами? - person Anders Zommarin; 24.02.2011
comment
Замечательно! Я знал, что это должно быть просто. Я пробовал ^fe25b6d, но не fe25b6d^, глупый я. Я повторяю вопрос, заданный @mrz; это хорошая функциональность, но полная история с одной командой было бы замечательно. - person Sedate Alien; 24.02.2011
comment
Я не верю, что Git имеет встроенный способ получить каждую вину, касающуюся номера строки (что имеет смысл, поскольку данная строка может не иметь постоянного номера строки на протяжении всей истории файла из-за вставок и удалений линий). - person Amber; 24.02.2011
comment
@Amber: Совершенно уверен, что вы правы в том, что этой функции не существует, но похоже, что ее можно реализовать наивно, просто сделав то, что сделал бы человек: обвинить его один раз, получить предоставленную информацию, обвинить в том, что , и так далее. - person Cascabel; 24.02.2011
comment
Конечно; вы, конечно, могли бы сделать это наивно с помощью довольно тривиального сценария оболочки. - person Amber; 24.02.2011
comment
git gui позволяет легко проверять историю строки, так как версии кликабельны. - person Zitrax; 07.06.2011
comment
Что -- здесь делает? Где я могу узнать об этом подробнее в документации? - person Abhijeet Rastogi; 13.10.2012
comment
@shadyabhi -- обычно используется в качестве разделителя в аргументах командной строки - в случае Git он обычно используется для отделения таких вещей, как хэши фиксации от списка имен файлов. - person Amber; 13.10.2012
comment
@Zitrax, о каком графическом интерфейсе git вы имеете в виду? - person HRJ; 22.11.2013
comment
Ответ Эмбер правильный, но мне он показался неясным; Синтаксис: git blame {sha1} -- {path/to/file} Примечание: -- используется для отделения древовидного sha1 от относительных путей к файлам. 1 Например: git blame master -- index.php. Полная благодарность Amber за то, что он все знает! :) - person ThorSummoner; 14.06.2014
comment
@AndersZommarin, пожалуйста, просмотрите ответ Томаса, чтобы узнать, что вы ищете. - person ssgao; 17.11.2015
comment
@Amber, извини, мне нужно получить такую ​​информацию из репозитория github. я хотел спросить, как мы можем получить ту же информацию от github API - person Kasun Siyambalapitiya; 31.01.2017
comment
в Emacs это работает как шарм - emacs.stackexchange.com/questions/31010/ - person hsestupin; 20.02.2018
comment
если вам просто нужна предыдущая фиксация, git blame HEAD^ или фиксация перед этим git blame HEAD^^ и т. д. - person alexanderbird; 24.05.2018
comment
добавление нескольких ignore-rev <commit-id> --ignore-rev <commit-id> позволяет игнорировать даже несколько уровней коммитов (которые можно настроить в файле конфигурации; если эти коммиты всегда необходимо игнорировать) - person gawkface; 10.02.2021

Вы можете использовать git log -L для просмотра эволюции ряда строк.

Например :

git log -L 15,23:filename.txt

означает «проследить эволюцию строк с 15 по 23 в файле с именем filename.txt».

person Navneet    schedule 04.09.2015
comment
Это надежный ответ, который отвечает на заданный выше вопрос Андерса Зоммарина о том, как увидеть изменения в определенных строках с течением времени. - person bigtex777; 11.09.2015
comment
К вашему сведению: git log -L ‹start›, ‹end›: ‹file› требует Git 1.8.4+ см .: git-scm.com/docs/git-log#git-log--Lltstartgtltendgtltfilegt для параметров синтаксиса. - person Neon; 28.12.2017
comment
У меня это не сработало со строкой, перемещенной из другого файла. - person Timmmm; 19.06.2020
comment
Я настоятельно рекомендую добавить -p, чтобы отобразить все изменения, похожие на git diff, например, например, для всего файла: git log -p filename.txt. - person Gabriel Staples; 02.03.2021

Ответ Эмбер правильный, но мне он показался неясным; Синтаксис:

git blame {commit_id} -- {path/to/file}

Примечание: -- используется для отделения древовидной формы sha1 от относительных путей к файлам. 1

Например:

git blame master -- index.html

Полная благодарность Amber за то, что он все знает! :)

person ThorSummoner    schedule 19.05.2014
comment
Я согласен с твоим мнением. Однако система комментариев слишком ограничена, чтобы четко представить всю информацию. Я добавил содержание этого ответа в комментарий; тем не менее, я настаиваю на том, чтобы оставить этот ответ местом для облегчения доступа. - person ThorSummoner; 14.06.2014
comment
Это должен быть отдельный пост или редактирование. Мне это нравится как отдельный ответ. - person Flimm; 01.09.2014

Возможно, вы захотите проверить:

git gui blame <filename>

Дает вам красивое графическое отображение изменений, таких как «git blame», но с интерактивными ссылками на строку для перехода к более ранним коммитам. Наведите указатель мыши на ссылки, чтобы открыть всплывающее окно с подробностями о фиксации. Не мои кредиты ... нашел здесь:

http://zsoltfabok.com/blog/2012/02/git-blame-line-history/

git gui - это графический интерфейс Tcl / Tc для git. Без каких-либо других параметров он запускает довольно простое, но полезное графическое приложение для фиксации файлов, фрагментов или даже отдельных строк и других подобных команд, таких как исправление, возврат, нажатие ... Это часть набора git stock. В Windows он включен в установщик. На debian - я не знаю о других системах * nix - его нужно устанавливать отдельно:

apt-get install git-gui

Из документов:

https://git-scm.com/docs/git-gui

ОПИСАНИЕ

Графический пользовательский интерфейс для Git на основе Tcl / Tk. git gui фокусируется на том, чтобы позволить пользователям вносить изменения в свой репозиторий, делая новые коммиты, изменяя существующие, создавая ветки, выполняя локальные слияния и извлекая / отправляя в удаленные репозитории.

В отличие от gitk, git gui фокусируется на генерации коммитов и аннотации одного файла и не показывает историю проекта. Однако он предоставляет действия меню для запуска сеанса gitk из git gui.

Известно, что git gui работает во всех популярных системах UNIX, Mac OS X и Windows (как Cygwin, так и MSYS). Насколько это возможно, соблюдаются рекомендации по пользовательскому интерфейсу для конкретных ОС, что делает git gui довольно родным интерфейсом для пользователей.

КОМАНДЫ

виноват

Запустить программу просмотра обвинений для указанного файла в данной версии (или в рабочем каталоге, если он не указан).

браузер

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

citool

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

версия

Показать текущую версию git gui.

person Holger Böhnke    schedule 20.09.2016
comment
У меня это не работает. Я могу щелкнуть изменение в данной строке, но это просто изменит представление для этой фиксации, и текущая строка теперь отображается как this: но как мне увидеть предыдущую версию строки и время ее добавления? - person BeeOnRope; 18.07.2018
comment
Это единственный известный мне вариант использования, где git gui - лучшее решение. - person cambunctious; 18.06.2019

Основываясь на предыдущем ответе, этот однострочный пакет bash должен дать вам то, что вы ищете. Он отображает историю ошибок git для конкретной строки определенного файла за последние 5 ревизий:

LINE=10 FILE=src/options.cpp REVS=5; for commit in $(git rev-list -n $REVS HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done

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

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

person Community    schedule 27.09.2012
comment
Обратите внимание, что это последняя ревизия $ REVS, в которой изменен $ FILE, а не последняя ревизия $ REVS, в которой изменилась $ LINE. - person Max Nanasy; 13.03.2013
comment
Какой ответ вы имеете в виду? - person Flimm; 01.09.2014
comment
Больше не помню. Возможно, я мог бы лучше обосновать свой ответ на будущее. - person Will Sheppard; 04.09.2014

Также есть recursive-blame. Его можно установить с помощью

npm install -g recursive-blame
person Thomas W    schedule 04.09.2015

Уникальное решение этой проблемы - использование git log, как объяснил Андре здесь:

git log -p -M --follow --stat -- path/to/your/file
person mannuscript    schedule 29.05.2016
comment
Я создал псевдоним, чтобы использовать это: git config --global alias.changes 'log -p -M --follow --stat --', а затем я могу просто ввести git changes path/to/your/file - person Tizio Fittizio; 05.07.2019
comment
Это, безусловно, лучший ответ и именно то, что я искал. Просто и элегантно. - person maesk; 06.02.2020

Если вы используете JetBrains Idea IDE (и производные), вы можете выбрать несколько строк, щелкнуть правой кнопкой мыши для контекстного меню, затем Git -> Показать историю для выбора. Вы увидите список коммитов, которые повлияли на выбранные строки:

введите описание изображения здесь

person warvariuc    schedule 18.12.2017
comment
Для меня это сработало лучше, чем другие ответы (с использованием IntelliJ). Потребовалось время, чтобы загрузить все ревизии, но ожидание того стоило. - person Steve Chambers; 15.04.2020

Начиная с Git 2.23, вы можете использовать git виноват --ignore-rev

Для примера, приведенного в вопросе, это будет:

git blame -L10,+1 src/options.cpp --ignore-rev fe25b6d

(однако это вопрос с подвохом, потому что fe25b6d - первая ревизия файла!)

person Michael Platings    schedule 06.09.2019

Основываясь на ответе Уилла Шепарда, его выходные данные будут включать повторяющиеся строки для коммитов, в которых не было изменений, поэтому вы можете отфильтровать их следующим образом (используя это ответ)

LINE=1 FILE=a; for commit in $(git rev-list HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

Обратите внимание, что я удалил аргумент REVS, и это относится к корневой фиксации. Это связано с наблюдением Макса Нанаси выше.

person DavidN    schedule 20.09.2015

Основываясь на ответе DavidN, и я хочу следить за переименованным файлом:

LINE=8 FILE=Info.plist; for commit in $(git log --format='%h%%' --name-only --follow -- $FILE | xargs echo | perl -pe 's/\%\s/,/g'); do hash=$(echo $commit | cut -f1 -d ','); fileMayRenamed=$(echo $commit | cut -f2 -d ','); git blame -n -L$LINE,+1 $hash -- $fileMayRenamed; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

ref: красиво отображать историю переименований файлов в журнале git

person Bill Chan    schedule 29.05.2016

Я использую этот небольшой сценарий bash, чтобы посмотреть историю обвинений.

Первый параметр: файл для просмотра

Последующие параметры: переданы в git blame.

#!/bin/bash
f=$1
shift
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    echo "--- $hash"
    git blame $@ $hash -- "$f" | sed 's/^/  /'
  done
}

Вы можете указать параметры обвинения, такие как -L 70, + 10, но лучше использовать поиск по регулярным выражениям git blame, потому что номера строк обычно "меняются" со временем.

person stangls    schedule 16.02.2014

Используйте ответ на основе stangls , я поместил этот скрипт в свой PATH (даже в Windows) как git-bh:

Это позволяет мне искать все коммиты, в которых было задействовано слово:

git bh path/to/myfile myWord

Сценарий:

#!/bin/bash
f=$1
shift
csha=""
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    res=$(git blame -L"/$1/",+1 $hash -- "$f" 2>/dev/null | sed 's/^/  /')
    sha=${res%% (*}
    if [[ "${res}" != "" && "${csha}" != "${sha}" ]]; then
      echo "--- ${hash}"
      echo "${res}"
      csha="${sha}"
    fi
  done
}
person VonC    schedule 11.07.2014

Я написал ublame инструмент python, который возвращает наивную историю фиксации файла, которая повлияла на данный поисковый запрос, вы найдете дополнительную информацию на þпроектировать страницу.

person kraymer    schedule 11.11.2020