Симпатичные графы веток

Я видел, что в некоторых книгах и статьях есть действительно симпатичные графики веток и коммитов git. Как я могу сделать высококачественные печатные изображения из истории Git?

38 ответов

Обновление: Этот ответ привлек гораздо больше внимания, чем заслуживает. Первоначально он был опубликован, потому что я думаю, что графики выглядят хорошо, и их можно нарисовать в Illustrator для публикации - и лучшего решения не было. Но теперь существует гораздо больше применимых ответов на этот вопрос, таких как fracz, Jubobs или Harry Lee! Пожалуйста, поднимите голос!

Обновление 2: я разместил улучшенную версию этого ответа в топологии ветвления Визуализация в git вопросе, так как это гораздо более уместно там. Эта версия включает в себя lg3 , которая показывает информацию об авторе и коммиттере, так что вы действительно должны это проверить. Оставляя этот ответ по историческим (& rep, я признаю) причинам, хотя я действительно испытываю желание просто удалить его.

2 ¢: у меня есть два псевдонима, которые я обычно добавляю ~/.gitconfig файл:

[alias]
lg1 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all
lg2 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n''          %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all
lg = !"git lg1"

git lg / git lg1 выглядит так:
мерзавец LG1

а также git lg2 выглядит так:
мерзавец LG2

Многие из ответов здесь хороши, но для тех, кто просто хочет получить ответ в одну строку без указания псевдонимов или чего-то еще, вот он:

git log --all --decorate --oneline --graph

Не все будут делать git log все время, но когда вам это нужно, просто помните:

" Собака " = Жуткий журнал - Всеохватывающий Экорат - О Нелайн - Г Раф

Для текстового вывода вы можете попробовать:

git log --graph --abbrev-commit --decorate --date=relative --all

или же:

git log --graph --oneline --decorate --all

или: вот псевдоним graphviz для рисования графа DAG.

Я лично пользуюсь gitx, gitk --all а также gitnub,

Gitgraph.js позволяет рисовать красивые ветки Git без хранилища. Просто напишите код Javascript, который настраивает ваши ветки и коммиты и отображает их в браузере.

var gitGraph = new GitGraph({
   template: "blackarrow",
   mode: "compact",
   orientation: "horizontal",
   reverseArrow: true
});

var master = gitGraph.branch("master").commit().commit();
var develop = gitGraph.branch("develop").commit();
master.commit();
develop.commit().commit();
develop.merge(master);

примерный график, созданный с помощью Gitgraph.js

или с metro шаблон:

GitGraph.js тема метро

или с сообщениями о фиксации, авторами и тегами:

GitGraph с коммитом сообщений

Проверьте это с помощью JSFiddle.

Создайте его с помощью Git Grapher от @bsara.

Построен на вершине TikZ & PGF, gitdags это небольшой пакет LaTeX, который позволяет вам легко создавать графики фиксации векторной графики и многое другое.

Автоматическая генерация графа коммитов существующего репозитория не является целью gitdags; графики, которые он производит, предназначены только для образовательных целей.

Я часто использую его для создания графиков для моих ответов на вопросы Git, в качестве альтернативы графам коммитов ASCII:

Вот пример такого графика, демонстрирующего эффекты простой перебазировки:

\documentclass{article}

\usepackage{subcaption}
\usepackage{gitdags}

\begin{document}

\begin{figure}
  \begin{subfigure}[b]{\textwidth}
    \centering
    \begin{tikzpicture}
      % Commit DAG
      \gitDAG[grow right sep = 2em]{
        A -- B -- { 
          C,
          D -- E,
        }
      };
      % Tag reference
      \gittag
        [v0p1]       % node name
        {v0.1}       % node text
        {above=of A} % node placement
        {A}          % target
      % Remote branch
      \gitremotebranch
        [origmaster]    % node name
        {origin/master} % node text
        {above=of C}    % node placement
        {C}             % target
      % Branch
      \gitbranch
        {master}     % node name and text 
        {above=of E} % node placement
        {E}          % target
      % HEAD reference
      \gitHEAD
        {above=of master} % node placement
        {master}          % target
    \end{tikzpicture}
    \subcaption{Before\ldots}
  \end{subfigure}

  \begin{subfigure}[b]{\textwidth}
    \centering
    \begin{tikzpicture}
      \gitDAG[grow right sep = 2em]{
        A -- B -- { 
          C -- D' -- E',
          {[nodes=unreachable] D -- E },
        }
      };
      % Tag reference
      \gittag
        [v0p1]       % node name
        {v0.1}       % node text
        {above=of A} % node placement
        {A}          % target
      % Remote branch
      \gitremotebranch
        [origmaster]    % node name
        {origin/master} % node text
        {above=of C}    % node placement
        {C}             % target
      % Branch
      \gitbranch
        {master}      % node name and text 
        {above=of E'} % node placement
        {E'}          % target
      % HEAD reference
      \gitHEAD
        {above=of master} % node placement
        {master}          % target
    \end{tikzpicture}
    \subcaption{\ldots{} and after \texttt{git rebase origin/master}}
  \end{subfigure}
  \caption{Demonstrating a typical \texttt{rebase}}
\end{figure}

\end{document}

Gitg - это клон Gitk и GitX для GNOME (он также работает на KDE и т. Д.), Который показывает довольно цветной график.

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

Он отлично работает с большими репозиториями и сложными графами зависимостей.

Примеры скриншотов, показывающие репозитории linux-git и linux-2.6:

линукс-мерзавец

Linux-2.6

Я только что написал один инструмент, который может генерировать симпатичные графы коммитов с помощью HTML/Canvas.

И предоставить плагин jQuery, который делает его простым в использовании.

[github] https://github.com/tclh123/commits-graph

Предварительный просмотр:

предварительный просмотр

Красивый и чистый табличный вывод git-графика для оболочек

с хешами, как обычно, помимо дерева графа

или в дополнительной колонке

Изменить: вы хотите начать прямо сейчас, не читая объяснений? Используйте псевдоним git, скрипт или фрагменты кода функции из раздела EDIT 5 ниже или даже самый удобный способ - EDIT 6.

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

Основной момент в моем подходе - считать только символы дерева, показываемые пользователю. Затем заполните их пробелами до индивидуальной длины.

Помимо git вам понадобятся эти инструменты

  • grep
  • вставить
  • printf
  • sed
  • seq
  • tr
  • Туалет

в основном на борту с любым дистрибутивом Linux.

Фрагмент кода

while IFS=+ read -r graph hash time branch message;do
  
  # count needed amount of whitespaces and create them
  whitespaces=$((9-$(sed -nl1000 'l' <<< "$graph" | grep -Eo '\\\\|\||\/|\ |\*|_' | wc -l)))
  whitespaces=$(seq -s'' $whitespaces|tr -d '[:digit:]')
  
  # show hashes besides the tree ...
  #graph_all="$graph_all$graph$(printf '%7s' "$hash")$whitespaces \n"
  
  # ... or in an own column
  graph_all="$graph_all$graph$whitespaces\n"
  hash_all="$hash_all$(printf '%7s' "$hash")  \n"
  
  # format all other columns
  time_all="$time_all$(printf '%12s' "$time") \n"
  branch_all="$branch_all$(printf '%15s' "$branch")\n"
  message_all="$message_all$message\n"
done < <(git log --all --graph --decorate=short --color --pretty=format:'+%C(bold 214)%<(7,trunc)%h%C(reset)+%C(dim white)%>(12,trunc)%cr%C(reset)+%C(214)%>(15,trunc)%d%C(reset)+%C(white)%s%C(reset)' && echo);

# paste the columns together and show the tablelike output
paste -d'' <(echo -e "$time_all") <(echo -e "$branch_all") <(echo -e "$graph_all") <(echo -e "$hash_all") <(echo -e "$message_all")

Чтобы вычислить необходимые пробелы, мы используем

  sed -nl1000 'l' <<< "$graph"

чтобы получить все символы (до 1000 в строке), чем выберите только символы дерева: * | / \ _ и пробелы с

  grep -Eo '\\\\|\||\/|\ |\*|_'

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

Чтобы получить рассчитанное количество пробелов, мы используем

  seq -s'' $whitespaces

и обрезать номера позиций с помощью

  tr -d '[:digit:]'

чем добавить их в конец нашей линии графика. Это оно!

У Git есть хорошая возможность форматировать длину спецификаторов вывода уже с синтаксисом'%><(amount_of_characters,truncate_option)', который добавляет пробелы слева '>' или справа '<' и может обрезать символы от начала 'ltrunc', среднего 'mtrunc' или конца 'trunc'.

Это важно, что выше использование PRINTF CMD то же значение длины для соответствующего столбца мерзавца.

Получайте удовольствие, создавая собственный чистый табличный вывод в соответствии с вашими потребностями.

Дополнительно:

Чтобы получить правильное значение длины, вы можете использовать следующий фрагмент

while read -r graph;do
    chars=$(sed -nl1000 'l' <<< "$graph" | grep -Eo '\\\\|\||\/|\ |\*|_' | wc -l)
    [[ $chars -gt ${max_chars:-0} ]] && max_chars=$chars
done < <(git log --all --graph --pretty=format:'')

и используйте $max_chars как указанное выше правильное значение длины.

РЕДАКТИРОВАТЬ 1: только что заметил, что символ подчеркивания также используется в дереве git, и соответствующим образом отредактируйте фрагменты кода выше. Если отсутствуют другие символы, оставьте комментарий.

РЕДАКТИРОВАТЬ 2: Если вы хотите избавиться от скобок вокруг записей веток и тегов, просто используйте "%D" вместо "%d" в команде git, как в EDIT 3.

РЕДАКТИРОВАТЬ 3: Может быть, вариант цвета "авто" - это тот, который вы больше всего предпочитаете для записей веток и тегов?

Измените эту часть команды git (цвет 214)

%C(214)%>(15,trunc)%D%C(reset)

на авто

%C(auto)%>(15,trunc)%D%C(reset)

РЕДАКТИРОВАТЬ 4: Или вам нравится ваш собственный цветовой микс для этой части, причудливый вывод с мигающей головой?

Чтобы иметь возможность сначала стилизовать заголовок, имена веток и теги, нам нужна опция цвета "auto" в нашей команде git, как в EDIT 3.

Затем мы можем заменить известные значения цвета нашими собственными, добавив эти 3 строки

 # branch name styling
 branch=${branch//1;32m/38;5;214m}
 # head styling
 branch=${branch//1;36m/3;5;1;38;5;196m}
 # tag styling
 branch=${branch//1;33m/1;38;5;222m}

непосредственно перед строкой

 branch_all="$branch_all$(printf '%15s' "$branch")\n"

в нашем фрагменте кода. Значения замены дают цвета, указанные выше.

Например, значение замены для головы:

3;5;1;38;5;196

где 3; расшифровывается курсивом, 5; для мигания и 1;38;5;196 для цвета. Для получения дополнительной информации начните здесь.Примечание: это поведение зависит от вашего любимого терминала и поэтому может быть непригодным для использования.

НО вы можете выбрать любое значение цвета, которое вам нравится.

ОБЗОР значений цвета git и эквивалентов ANSI

Здесь вы найдете список с опцией git color / style.

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

for ((i=0;i<=255;i++));do
  while IFS='+' read -r tree hash;do 
    echo -e "$(printf '%-10s' "(bold $i)") $hash  $(sed -nl500 'l' <<< "$hash"|grep -Eom 1 '[0-9;]*[0-9]m'|tr -d 'm')"
  done < <(git log --all --graph --decorate=short --color --pretty=format:'+%C(bold '$i')%h%C(reset)'|head -n 1)
done

в пути вашего проекта git, который использует первую фиксацию из вывода журнала git.

РЕДАКТИРОВАТЬ 5: Как упомянул член "Андрас Деак", есть несколько способов использования этого кода:

1) как псевдоним:

псевдоним не принимает параметры, но функция может, поэтому просто определите в вашем.bashrc

   function git_tably () {
     unset branch_all graph_all hash_all message_all time_all max_chars

     ### add here the same code as under "2) as a shell-script" ###

   }

и вызовите функцию git_tably (производную от tablelike) прямо под вашим путем к проекту git или откуда угодно, указав путь к проекту git в качестве первого параметра.

2) в виде shell-скрипта:

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

# edit your color/style preferences here or use empty values for git auto style
tag_style="1;38;5;222"
head_style="1;3;5;1;38;5;196"
branch_style="38;5;214"

# determine the max character length of your git tree
while IFS=+ read -r graph;do
  chars_count=$(sed -nl1000 'l' <<< "$graph" | grep -Eo '\\\\|\||\/|\ |\*|_' | wc -l)
  [[ $chars_count -gt ${max_chars:-0} ]] && max_chars=$chars_count
done < <(cd "${1:-"$PWD"}" && git log --all --graph --pretty=format:'')

# create the columns for your prefered tablelike git graph output
while IFS=+ read -r graph hash time branch message;do

  # count needed amount of whitespaces and create them
  whitespaces=$(($max_chars-$(sed -nl1000 'l' <<< "$graph" | grep -Eo '\\\\|\||\/|\ |\*|_' | wc -l)))
  whitespaces=$(seq -s'' $whitespaces|tr -d '[:digit:]')

  # show hashes besides the tree ...
  #graph_all="$graph_all$graph$(printf '%7s' "$hash")$whitespaces \n"

  # ... or in an own column
  graph_all="$graph_all$graph$whitespaces\n"
  hash_all="$hash_all$(printf '%7s' "$hash")  \n"

  # format all other columns
  time_all="$time_all$(printf '%12s' "$time") \n"
  branch=${branch//1;32m/${branch_style:-1;32}m}
  branch=${branch//1;36m/${head_style:-1;36}m}
  branch=${branch//1;33m/${tag_style:-1;33}m}
  branch_all="$branch_all$(printf '%15s' "$branch")\n"
  message_all="$message_all$message\n"

done < <(cd "${1:-"$PWD"}" && git log --all --graph --decorate=short --color --pretty=format:'+%C(bold 214)%<(7,trunc)%h%C(reset)+%C(dim white)%>(12,trunc)%cr%C(reset)+%C(auto)%>(15,trunc)%D%C(reset)+%C(white)%s%C(reset)' && echo);

# paste the columns together and show the tablelike output
paste -d'' <(echo -e "$time_all") <(echo -e "$branch_all") <(echo -e "$graph_all") <(echo -e "$hash_all") <(echo -e "$message_all")

3) как псевдоним git:

Возможно, самый удобный способ - добавить псевдоним git в ваш.gitconfig

[color "decorate"]
    HEAD = bold blink italic 196
    branch = 214
    tag = bold 222
    
[alias]
    count-log = log --all --graph --pretty=format:''
    tably-log = log --all --graph --decorate=short --color --pretty=format:'+%C(bold 214)%<(7,trunc)%h%C(reset)+%C(dim white)%>(12,trunc)%cr%C(reset)+%C(auto)%>(15,trunc)%D%C(reset)+%C(white)%s%C(reset)'
    tably     = !bash -c '"                                                                                                    \
                  while IFS=+ read -r graph;do                                                                                 \
                    chars_count=$(sed -nl1000 \"l\" <<< \"$graph\" | grep -Eo \"\\\\\\\\\\\\\\\\|\\||\\/|\\ |\\*|_\" | wc -l); \
                    [[ $chars_count -gt ${max_chars:-0} ]] && max_chars=$chars_count;                                          \
                  done < <(git count-log && echo);                                                                             \
                  while IFS=+ read -r graph hash time branch message;do                                                        \
                    chars=$(sed -nl1000 \"l\" <<< \"$graph\" | grep -Eo \"\\\\\\\\\\\\\\\\|\\||\\/|\\ |\\*|_\" | wc -l);       \
                    whitespaces=$(($max_chars-$chars));                                                                        \
                    whitespaces=$(seq -s\" \" $whitespaces|tr -d \"[:digit:]\");                                               \
                    graph_all=\"$graph_all$graph$whitespaces\n\";                                                              \
                    hash_all=\"$hash_all$(printf \"%7s\" \"$hash\")  \n\";                                                     \
                    time_all=\"$time_all$(printf \"%12s\" \"$time\") \n\";                                                     \
                    branch_all=\"$branch_all$(printf \"%15s\" \"$branch\")\n\";                                                \
                    message_all=\"$message_all$message\n\";                                                                    \
                  done < <(git tably-log && echo);                                                                             \
                  paste -d\" \" <(echo -e \"$time_all\") <(echo -e \"$branch_all\") <(echo -e \"$graph_all\")                  \
                                <(echo -e \"$hash_all\") <(echo -e \"$message_all\");                                          \
                '"

Чем просто позвони git tably под любой путь проекта.

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

Еще один интересный вариант - выбрать цвета дерева, которые вам больше всего нравятся.

[log]
    graphColors = bold 160, blink 231 bold 239, bold 166, bold black 214, bold green, bold 24, cyan

это дает вам сумасшедший вид, но всегда табличный вывод журнала git

Слишком много миганий! Просто чтобы продемонстрировать, что возможно. Слишком мало указанных цветов приводит к повторению цветов.

Полный справочник по.gitconfig находится всего в одном клике.

РЕДАКТИРОВАТЬ 6: Благодаря вашим положительным голосам я улучшил фрагмент. Теперь вы можете кормить его практически любой командой git log и больше не нужно адаптировать код. Попытайся!

Как это работает?

  • как всегда, определите свои команды журнала git в своем.gitconfig
  • определить положительный номер столбца дерева (необязательно), где показан график git

Тогда просто позвони

git tably YourLogAlias

или

git tably YourLogAlias TreeColNumber

где TreeColNumber перезаписывает всегда определенное значение сверху.

Ограничение:

  • перед каждым заполнителем фиксации в вашей команде журнала вы должны использовать
    %><(<N>[,ltrunc|mtrunc|trunc]), с одним из вариантов усечения

    (пояснения по синтаксису см. https://git-scm.com/docs/pretty-formats),

    однако последний заполнитель фиксации любой новой строки можно использовать без него

  • если для украшения нужны дополнительные символы, например (committer: , < а также >) в

    ...%C(dim white)(committer: %cn% <%ce>)%C(reset)...

    чтобы получить табличный вывод, они должны быть написаны непосредственно до и после заполнителя фиксации

    ...%C(dim white)%<(25,trunc)(committer: %cn%<(25,trunc) <%ce>)%C(reset)...

  • если --pretty=format: вариант не последний закройте его %C(reset) как обычно

  • вы можете разместить график git в каждом столбце, если вы не используете непустые символы новой строки %n...

  • вы должны выбрать и использовать разделитель столбцов, который может вызвать проблемы, если не является уникальным

  • имя определенного вами номера столбца дерева для определенного псевдонима журнала должно быть YourLogAlias-col

  • используйте параметр --color для цветного вывода

  • по сравнению с обычным выводом журнала git, этот медленный, но приятный

Теперь улучшенный фрагмент для вашего.gitconfig

[color "decorate"]
    HEAD = bold blink italic 196
    branch = 214
    tag = bold 222
    
[alias]

    # delimiter used in every mylog alias as column seperator
    delim     = ^
    # short overview about the last hashes without graph
    mylog     = log --all --decorate=short --color --pretty=format:'^%C(dim white)%>(12,trunc)%cr%C(reset)^%C(bold 214)%<(7,trunc)%h%C(reset)' -5
    # log with hashes besides graph tree
    mylog2    = log --all --graph --decorate=short --color --pretty=format:'%C(bold 214)%<(7,trunc)%h%C(reset)^%C(dim white)%>(12,trunc)%cr%C(reset)^%C(auto)%>(15,trunc)%D%C(reset)^%C(white)%<(80,trunc)%s%C(reset)'
    mylog2-col= 3
    # log with hashes in an own column and more time data
    mylog3    = log --all --graph --decorate=short --color --pretty=format:'^%C(dim white)%>(12,trunc)%cr%C(reset)^%C(cyan)%<(10,trunc)%cs%C(reset)^%C(bold 214)%<(7,trunc)%h%C(reset)^%C(auto)%<(15,trunc)%D%C(reset)^%C(white)%s%C(reset)'
    mylog3-col= 4

    tably = !bash -c '"                                                                                                              \
              declare -A col_length;                                                                                                 \
              delim=$(git config alias.delim);                                                                                       \
              git_log_cmd=$(git config alias.$1);                                                                                    \
              git_tre_col=${2:-$(git config alias.$1-col)};                                                                          \
                                                                                                                                     \
              i=0;                                                                                                                   \
              n=0;                                                                                                                   \
              while IFS= read -r line; do                                                                                            \
                ((n++));                                                                                                             \
                while read -d\"$delim\" -r col_info;do                                                                               \
                  ((i++));                                                                                                           \
                  [[ -z \"$col_info\" ]] && col_length[\"$n:$i\"]=${col_length[\"${last[$i]:-1}:$i\"]} && ((i--)) && continue;       \
                  [[ $i -gt ${i_max:-0} ]] && i_max=$i;                                                                              \
                  col_length[\"$n:$i\"]=$(grep -Eo \"\\([0-9]*,[lm]*trunc\\)\" <<< \"$col_info\" | grep -Eo \"[0-9]*\" | head -n 1); \
                  [[ -n \"${col_length[\"$n:$i\"]}\" ]] && last[$i]=$n;                                                              \
                  chars_extra=$(grep -Eo \"\\trunc\\).*\" <<< \"$col_info\");                                                        \
                  chars_extra=${chars_extra#trunc)};                                                                                 \
                  chars_begin=${chars_extra%%\\%*};                                                                                  \
                  chars_extra=${chars_extra#*\\%};                                                                                   \
                  case \" ad aD ae aE ai aI al aL an aN ar as at b B cd cD ce cE ci cI cl cL cn cN cr                                \
                          cs ct d D e f G? gd gD ge gE GF GG GK gn gN GP gs GS GT h H N p P s S t T \" in                            \
                   *\" ${chars_extra:0:2} \"*)                                                                                       \
                     chars_extra=${chars_extra:2};                                                                                   \
                     chars_after=${chars_extra%%\\%*};                                                                               \
                     ;;                                                                                                              \
                   *\" ${chars_extra:0:1} \"*)                                                                                       \
                     chars_extra=${chars_extra:1};                                                                                   \
                     chars_after=${chars_extra%%\\%*};                                                                               \
                     ;;                                                                                                              \
                   *)                                                                                                                \
                     echo \"No Placeholder found. Probably no tablelike output.\";                                                   \
                     continue;                                                                                                       \
                     ;;                                                                                                              \
                  esac ;                                                                                                             \
                  if [[ -n \"$chars_begin$chars_after\" ]];then                                                                      \
                    len_extra=$(echo \"$chars_begin$chars_after\" | wc -m);                                                          \
                    col_length["$n:$i"]=$((${col_length["$n:$i"]}+$len_extra-1));                                                    \
                  fi;                                                                                                                \
                                                                                                                                     \
                done <<< \"${line#*=format:}$delim\";                                                                                \
                i=1;                                                                                                                 \
              done <<< \"$(echo -e \"${git_log_cmd//\\%n/\\\\n}\")\";                                                                \
                                                                                                                                     \
              case \"$git_log_cmd\" in                                                                                               \
                *\"--author-date-order\"*)                                                                                           \
                  log_count=\"log --all --graph --author-date-order --pretty=format:\\ \";                                           \
                  ;;                                                                                                                 \
                *\"--date-order\"*)                                                                                                  \
                  log_count=\"log --all --graph --date-order --pretty=format:\\ \";                                                  \
                  ;;                                                                                                                 \
                *\"--topo-order\"*)                                                                                                  \
                  log_count=\"log --all --graph --topo-order --pretty=format:\\ \";                                                  \
                  ;;                                                                                                                 \
                *)                                                                                                                   \
                  log_count=\"log --all --graph --pretty=format:\\ \";                                                               \
                  ;;                                                                                                                 \
              esac;                                                                                                                  \
              while IFS= read -r graph;do                                                                                            \
                chars_count=$(sed -nl1000 \"l\" <<< \"$graph\" | grep -Eo \"\\\\\\\\\\\\\\\\|\\||\\/|\\ |\\*|_\" | wc -l);           \
                [[ ${chars_count:-0} -gt ${col_length["1:1"]:-0} ]] && col_length["1:1"]=$chars_count;                               \
              done < <([[ -n \"$(grep -F graph <<< \"$git_log_cmd\")\" ]] && git $log_count && echo);                                \
                                                                                                                                     \
              l=0;                                                                                                                   \
              while IFS= read -r line;do                                                                                             \
                c=0;                                                                                                                 \
                ((l++));                                                                                                             \
                [[ $l -gt $n ]] && l=1;                                                                                              \
                while IFS= read -d\"$delim\" -r col_content;do                                                                       \
                  ((c++));                                                                                                           \
                  if [[ $c -eq 1 ]];then                                                                                             \
                    [[ -n \"$(grep -F \"*\" <<< \"$col_content\")\" ]] || l=2;                                                       \
                    chars=$(sed -nl1000 \"l\" <<< \"$col_content\" | grep -Eo \"\\\\\\\\\\\\\\\\|\\||\\/|\\ |\\*|_\" | wc -l);       \
                    whitespaces=$((${col_length["1:1"]}-$chars));                                                                    \
                    whitespaces=$(seq -s\" \" $whitespaces|tr -d \"[:digit:]\");                                                     \
                    col_content[1]=\"${col_content[1]}$col_content$whitespaces\n\";                                                  \
                  else                                                                                                               \
                    col_content[$c]=\"${col_content[$c]}$(printf \"%-${col_length[\"$l:$c\"]}s\" \"${col_content:-\"\"}\")\n\";      \
                  fi;                                                                                                                \
                done <<< \"$line$delim\";                                                                                            \
                for ((k=$c+1;k<=$i_max;k++));do                                                                                      \
                  empty_content=\"$(printf \"%-${col_length[\"$l:$k\"]:-${col_length[\"${last[$k]:-1}:$k\"]:-0}}s\" \"\")\";         \
                  col_content[$k]=\"${col_content[$k]}$empty_content\n\";                                                            \
                done;                                                                                                                \
              done < <(git $1 && echo);                                                                                              \
                                                                                                                                     \
              while read col_num;do                                                                                                  \
                if [[ -z \"$cont_all\" ]];then                                                                                       \
                  cont_all=${col_content[$col_num]};                                                                                 \
                else                                                                                                                 \
                  cont_all=$(paste -d\" \" <(echo -e \"$cont_all\") <(echo -e \"${col_content[$col_num]}\"));                        \
                fi;                                                                                                                  \
              done <<< $(seq 2 1 ${git_tre_col:-1};seq 1;seq $((${git_tre_col:-1}+1)) 1 $i_max);                                     \
              echo -e \"$cont_all\";                                                                                                 \
              "' "git-tably"

Полученные результаты:

или с новым TreeColNumber на лету

СНОВА: получайте удовольствие, создавая собственный чистый табличный вывод в соответствии с вашими потребностями.

SourceTree действительно хороший. Он действительно выводит на экран красивый и средний размер истории и ветвления: (следующее делается на экспериментальном проекте Git только для просмотра некоторых веток). Поддерживает Windows 7+ и Mac OS X 10.6+.

http://www.sourcetreeapp.com/

Я написал веб-инструмент для преобразования журналов git в красивые SVG-графики: Bit-Booster - инструмент для рисования графиков в автономном режиме

Загрузить вывод из git log --pretty='%h|%p|%d' прямо в инструмент, а затем нажмите на ссылку "загрузить graph.svg".

Этот инструмент предназначен исключительно для клиентской части, поэтому никакие ваши данные Git не передаются на мой сервер. Вы также можете сохранить HTML + JS локально и запустить его, используя URL "file: ///". Проверено на Chrome 48 и Firefox 43 на Ubuntu 12.04.

Он генерирует HTML, который может быть размещен непосредственно на любой странице (включая движок блогов blogpot!). Посмотрите на некоторые сообщения в блоге здесь:

http://bit-booster.blogspot.ca/

Вот скриншот образца HTML-файла, созданного инструментом:

http://bit-booster.com/graph.html (инструмент)

git-forest это отличный Perl-скрипт, который я использую более года, и я вряд ли использую git log команда непосредственно больше.

Вот некоторые вещи, которые мне нравятся в этом сценарии:

  • Он использует символы Юникода для рисования линий на графике, давая более непрерывный вид линий графика.
  • Вы можете объединить --reverse с выводом графика, что невозможно с обычным git log команда.
  • Оно использует git log внутренне, чтобы захватить список коммитов, так что все опции, которые вы передаете git log также может быть передан в этот скрипт.

У меня есть псевдоним, использующий git-forest следующее:

[alias]
tree = "forest --pretty=format:\"%C(red)%h %C(magenta)(%ar) %C(blue)%an %C(reset)%s\" --style=15 --reverse"

Вот как выглядит вывод на терминале:

Основываясь на скрипте Graphviz, который я нашел в ответе на связанный вопрос, я взломал скрипт ruby, который создает сводное представление хранилища git. Он исключает всю линейную историю и просто показывает "интересные" коммиты, то есть те, у которых несколько родителей, несколько детей или на которые указывает ветка или тег. Вот фрагмент графика, который он генерирует для jquery:

образец jquery

git-big-picture и BranchMaster - похожие инструменты, которые пытаются показать только высокоуровневую структуру графика, показывая только то, как связаны теги, ветви, слияния и т. д.

У этого вопроса есть еще несколько вариантов.

Я добавил три пользовательских команды: git tree, git stree а также git vtree, Я пойду по ним в таком порядке.

[alias]
    tree = log --all --graph --decorate=short --color --format=format:'%C(bold blue)%h%C(reset) %C(auto)%d%C(reset)\n         %C(black)[%cr]%C(reset)  %x09%C(black)%an: %s %C(reset)'

С git stree а также git vtree Я использую bash, чтобы помочь с форматированием.

[alias]
    logx = log --all --graph --decorate=short --color --format=format:'%C(bold blue)%h%C(reset)+%C(dim black)(%cr)%C(reset)+%C(auto)%d%C(reset)++\n+++       %C(bold black)%an%C(reset)%C(black): %s%C(reset)'
    stree = !bash -c '"                                                                             \
        while IFS=+ read -r hash time branch message; do                                            \
            timelength=$(echo \"$time\" | sed -r \"s:[^ ][[]([0-9]{1,2}(;[0-9]{1,2})?)?m::g\");     \
            timelength=$(echo \"16+${#time}-${#timelength}\" | bc);                                 \
            printf \"%${timelength}s    %s %s %s\n\" \"$time\" \"$hash\" \"$branch\" \"\";          \
        done < <(git logx && echo);"'

git_stree


[alias]
    logx = log --all --graph --decorate=short --color --format=format:'%C(bold blue)%h%C(reset)+%C(dim black)(%cr)%C(reset)+%C(auto)%d%C(reset)++\n+++       %C(bold black)%an%C(reset)%C(black): %s%C(reset)'
    vtree = !bash -c '"                                                                             \
        while IFS=+ read -r hash time branch message; do                                            \
            timelength=$(echo \"$time\" | sed -r \"s:[^ ][[]([0-9]{1,2}(;[0-9]{1,2})?)?m::g\");     \
            timelength=$(echo \"16+${#time}-${#timelength}\" | bc);                                 \
            printf \"%${timelength}s    %s %s %s\n\" \"$time\" \"$hash\" \"$branch\" \"$message\";  \
        done < <(git logx && echo);"'

git_vtree


РЕДАКТИРОВАТЬ: Это работает с GIT версии 1.9a. Значение цвета 'auto', по-видимому, дебютирует в этом выпуске. Это хорошее дополнение, потому что названия ветвей получат другой цвет. Это облегчает различие между локальной и удаленной ветвями, например.

Для более подробного текстового вывода, пожалуйста, попробуйте:

git log --graph --date-order -C -M --pretty=format:"<%h> %ad [%an] %Cgreen%d%Creset %s" --all --date=short

Вы можете написать псевдоним в $HOME/.gitconfig

[alias]
    graph = log --graph --date-order -C -M --pretty=format:\"<%h> %ad [%an] %Cgreen%d%Creset %s\" --all --date=short

Это мое мнение по этому вопросу:

Скриншот:

Скриншот

Использование:

git hist - Показать историю текущей ветки

git hist --all - Показать график всех филиалов (включая пульты)

git hist master devel - Показать отношения между двумя или более ветвями

git hist --branches - Показать все местные филиалы

добавлять --topo-order сортировать коммиты топологически, а не по дате (по умолчанию в этом псевдониме)

Выгоды:

  • Выглядит так же, как простой --decorateс разными цветами для разных названий веток
  • Добавляет адрес коммитера
  • Добавляет фиксированную относительную и абсолютную дату
  • Сортирует совершает по дате

Настроить:

git config --global alias.hist "log --graph --date-order --date=short \
--pretty=format:'%C(auto)%h%d %C(reset)%s %C(bold blue)%ce %C(reset)%C(green)%cr (%cd)'"

Зависит от того, как они выглядели. Я использую GITX, который делает фотографии, подобные этой:

простой сюжет

Вы можете сравнить git log --graph против gitk при 24-способном слиянии осьминогов (первоначально с http://clojure-log.n01se.net/date/2008-12-24.html):

24-ходовой мерзавец осьминога сливается. Исходный URL был <code> http://lwn.net/images/ns/kernel/gitk-octopus.png </ code http://lwn.net/images/ns/kernel/gitk-octopus.png

VS Code имеет потрясающее расширение

https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph

gitg: средство просмотра репозиториев на основе gtk, это новое, но интересное и полезное
http://git.gnome.org/browse/gitg
Я использую это в настоящее время

Хотя иногда я использую gitg, всегда возвращаюсь к командной строке:

[alias]
    #quick look at all repo
    loggsa = log --color --date-order --graph --oneline --decorate --simplify-by-decoration --all
    #quick look at active branch (or refs pointed)
    loggs  = log --color --date-order --graph --oneline --decorate --simplify-by-decoration
    #extend look at all repo
    logga  = log --color --date-order --graph --oneline --decorate --all
    #extend look at active branch
    logg   = log --color --date-order --graph --oneline --decorate
    #Look with date
    logda  = log --color --date-order --date=local --graph --format=\"%C(auto)%h%Creset %C(blue bold)%ad%Creset %C(auto)%d%Creset %s\" --all
    logd   = log --color --date-order --date=local --graph --format=\"%C(auto)%h%Creset %C(blue bold)%ad%Creset %C(auto)%d%Creset %s\"        
    #Look with relative date
    logdra = log --color --date-order --graph --format=\"%C(auto)%h%Creset %C(blue bold)%ar%Creset %C(auto)%d%Creset %s\" --all
    logdr = log --color --date-order --graph --format=\"%C(auto)%h%Creset %C(blue bold)%ar%Creset %C(auto)%d%Creset %s\"  

    loga   = log --graph --color --decorate --all

    # For repos without subject body commits (vim repo, git-svn clones)
    logt  = log --graph --color --format=\"%C(auto)%h %d %<|(100,trunc) %s\"
    logta  = log --graph --color --format=\"%C(auto)%h %d %<|(100,trunc) %s\" --all        
    logtsa = log --graph --color --format=\"%C(auto)%h %d %<|(100,trunc) %s\" --all --simplify-by-decoration 

Как вы можете видеть, это почти клавиатурные псевдонимы, основанные на:

  • --цвет: чистый вид
  • --graph: визуализировать родителей
  • --date-order: самый понятный взгляд на репо
  • - украшать: кто есть кто
  • --oneline: много раз все, что вам нужно знать о коммите
  • --simplify-by-украшением: базовый для первого взгляда (только теги, соответствующие слияния, ветви)
  • --all: сохранение нажатий клавиш со всеми псевдонимами с и без этой опции
  • --date= относительный (%ar): Понимать активность в репо (иногда ветка - это всего лишь несколько коммитов рядом с мастером, но месяцы назад от него)

Смотрите в последней версии git (1.8.5 и выше) вы можете воспользоваться%C(авто) в декорации заполнителя%d

Отсюда все, что вам нужно, это хорошее понимание gitrevisions для фильтрации всего, что вам нужно (что-то вроде master..develop, где --simplify-merges может помочь с долгосрочными ветвями)

Мощь командной строки - это быстрое конфигурирование, основанное на ваших потребностях (понимайте, что репозиторий не является уникальной конфигурацией журнала ключей, поэтому иногда необходимо добавить --numstat, или --raw, или --name-status. Здесь git log а псевдонимы быстрые, мощные и (со временем) самый красивый график, которого вы можете достичь. Более того, с выводом по умолчанию через пейджер (скажем, меньше) вы всегда можете быстро искать в результатах. Не уверен? Вы всегда можете проанализировать результат с такими проектами, как gitgraph

Я предлагаю tig https://github.com/jonas/tig, намного лучший инструмент командной строки для git.

Вы можете использовать homebrew для установки TIG на MacOS:

$ brew install tig
$ tig

Слегка подправив удивительный ответ Слиппа, вы можете использовать его псевдонимы для входа только в одну ветку:

[alias]
lgBranch1 = log --graph --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(bold white)— %an%C(reset)%C(bold yellow)%d%C(reset)' --abbrev-commit --date=relative
lgBranch2 = log --graph --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n''          %C(white)%s%C(reset) %C(bold white)— %an%C(reset)' --abbrev-commit
lg = !"git lg1"

Оставляя --all теперь вы можете сделать

git lgBranch1 <branch name>

или даже

git lgBranch1 --all

У меня есть это git log псевдоним в ~/.gitconfig чтобы просмотреть историю графика:

[alias]
l = log --all --graph --pretty=format:'%C(auto)%h%C(auto)%d %s %C(dim white)(%aN, %ar)'

С этим на месте, git l выведет что-то вроде:

В Git 2.12 + вы даже можете настроить цвета линий графика, используя log.graphColors Вариант конфигурации.

Что касается формата журналов, он похож на --oneline, с добавлением имени автора (с уважением .mailmap) и относительная дата автора. Обратите внимание, что %C(auto) синтаксис, который говорит Git использовать цвета по умолчанию для хэша коммита и т. д., поддерживается в Git> = 1.8.3.

Ты пробовал gitk или же gitk --all? Однако он не имеет функции печати / сохранения IMG как функции.

Цветная версия ракушек, более похожая на ветки.

Некоторые другие ответы показывают, что деревья графов красиво окрашены внешними инструментами, частично с информацией о цветных линиях. Это мой подход к оболочкам, который представляет собой комбинацию с моим первым ответом здесь для вывода в виде таблицы. ( /questions/38120306/simpatichnyie-grafyi-vetok/55111015#55111015)

Особенности:

  • Вы можете определить все цвета дерева
  • Вы можете раскрасить каждый столбец, как дерево
  • Вы можете разместить столбец дерева в разных местах
  • Вы можете использовать различные псевдонимы журнала git
  • Вы можете определить номер столбца дерева для каждого псевдонима
  • Вы можете вставить его в less -r для больших историй

Как вы это используете:

Определите псевдоним журнала git, как в нескольких показанных ответах, например, из Slipp D., albfan, kaoru, с указанными ниже инструкциями по форматированию и вставьте его в свой.gitconfig вместе с фрагментом кода. Вызовите его со своего пути проекта, как обычно, с помощью

git colored YourLogAlias или

git colored YourLogAlias TreeColumnNumber

где TreeColNumber заменяет значение, уже определенное в.gitconfig.

Инструкции по форматированию:

  • использовать уникальный символ в качестве разделителя столбцов для каждого заполнителя фиксации, т.е. ^
    ...format:'%h%cr%s' ->
    ...format:'^%h^%cr^%s'
  • раскрасьте весь столбец в один цвет или оставьте поле пустым, чтобы использовать соответствующие цвета дерева
    ...format:'^%h^%cr^%s' ->
    ...format:'^%h^%cr^%C(white)%s%C(reset)' (хеши и время в цвете дерева)
  • вы должны указать ширину любого столбца с помощью %><(<N>[,ltrunc|mtrunc|trunc]) с одним из параметров усечения, но любой последний заполнитель фиксации в строке можно использовать без него
    ...format:'^%h^%cr^%C(white)%s%C(reset)' ->
    ...format:'^%<(7,trunc)%h^%<(12,trunc)%cr^%C(white)%<(50,trunc)%s%C(reset)'
  • если вам нужны дополнительные символы оформления, поместите их непосредственно вокруг заполнителя фиксации, т.е. Commit:
    ...^%C(white)%<(50,trunc)%s%C(reset)... ->
    ...^%C(white)%<(50,trunc)Commit:%s%C(reset)...
  • если вы используете символы новой строки %n поместите их перед разделителем столбцов или в конце
    ...^%C(white)%<(50,trunc)Commit:%s%C(reset)' ->
    ...%n^%C(white)%<(50,trunc)Commit:%s%C(reset)%n'
  • если вы используете цвета столбцов, например %C(white) выше вам нужно добавить --color вариант
    ...format:'^%<(7,trunc)%h... ->
    ...--color...format:'^%<(7,trunc)%h...

Разное:

  • для псевдонимов журнала git с непустыми символами новой строки ...%n%CommitPlaceholder..., вы можете разместить график git в каждом столбце n+1, только если все n-ые столбцы каждой строки существуют и используют одинаковую ширину

  • YourLogAlias-col должен быть именем TreeColumnNumber, когда он настроен для псевдонима журнала YourLogAlias в.gitconfig

  • по сравнению с обычным выводом журнала git, этот медленный, но приятный

Примеры:

Фрагмент кода:

Добавьте следующие строки в свой.gitconfig

# Define your unique column seperator
delim      = ^

# Define your git log aliases and optional tree column numbers
lgc1       = log --all --graph --color --pretty=format:'^%<(7,trunc)%h^%C(white)%<(15,trunc)- %ar -%C(reset)^%<(35,trunc)%s^%C(white)%an%C(reset)'

lgc2       = log --all --graph --color --pretty=format:'%D^%<(7,trunc)%h^%<(35,trunc)%s^%C(white)%<(20,trunc)%an%C(reset)^%C(white) (%ar)%C(reset)'
lgc2-col   = 2

lgc3       = log --all --graph --color --pretty=format:'%<(7,trunc)%h%d^%<(11,trunc)%cs%C(reset)^%s%n^%C(white)%<(11,trunc)%cr%C(reset)^%C(white)%<(25,trunc)From %an%C(reset)^%C(white)%ae%C(reset)%n'
lgc3-col   = 2

lgc4       = log --all --graph --color --pretty=format:'%h^%C(white)%<(25,trunc)%an%C(reset)^%C(white)%<(31,trunc)%aD%C(reset)^%s%n^%C(dim white)%<(25,trunc)%ae%C(reset)^%>(31,trunc)%D%C(reset)%n'
lgc4-col   = 3

# Define your whitespace seperated tree color list
color-list = "1;38;5;222 1;38;5;69 1;38;5;250 1;38;5;70 1;31 1;38;5;93 1;33 2;38;5;11 1;38;5;48 1;35 1;32 1;38;5;111 1;38;5;160 1;38;5;130 1;36 38;5;21"

# This is the bash snippet which does all the magic
char-spec  = '
colored    = ........

Пожалуйста, замените colored = ... определение с этим из второй части ниже:

colored = !bash -c '" \
   \
   \
   declare -A col_length col_colored; \
   delim=$(git config alias.delim); \
   char_spec=$(git config alias.char-spec); \
   git_log_cmd=$(git config alias.$1); \
   graph_col=${2:-$(git config alias.$1-col)}; \
   color_list=( $(git config alias.color-list) ); \
   graph_col=${2:-$(git config alias.$1-col)}; \
   [[ -z \"$graph_col\" ]] && graph_col=1; \
   [[ -z \"$git_log_cmd\" ]] && { git $1;exit; }; \
   [[ -z \"${color_list[*]// }\" ]] && { echo \"No colors specified via color-list under section [alias] in your .gitconfig\";exit; }; \
   \
   \
   i=0; \
   n=0; \
   while IFS= read -r line; do \
     ((n++)); \
     while read -d\"$delim\" -r col_info;do \
       ((i++)); \
       [[ -z \"$col_info\" ]] && col_length[\"$n:$i\"]=${col_length[\"${last[$i]:-1}:$i\"]} && ((i--)) && continue; \
       [[ $i -gt ${i_max:-0} ]] && i_max=$i; \
       [[ \"${col_info:1:1}\" = \"C\" ]] && col_colored[\"$n:$i\"]=1; \
       col_length[\"$n:$i\"]=$(grep -Eo \"\\([0-9]*,[lm]*trunc\\)\" <<< \"$col_info\" | grep -Eo \"[0-9]*\" | head -n 1); \
       [[ -n \"${col_length[\"$n:$i\"]}\" ]] && last[$i]=$n; \
       chars_extra=$(grep -Eo \"\\trunc\\).*\" <<< \"$col_info\"); \
       chars_extra=${chars_extra#trunc)}; \
       chars_begin=${chars_extra%%\\%*}; \
       chars_extra=${chars_extra%$char_spec*}; \
       chars_extra=${chars_extra#*\\%}; \
       case \" ad aD ae aE ai aI al aL an aN ar as at b B cd cD ce cE ci cI cl cL cn cN cr \
               cs ct d D e f G? gd gD ge gE GF GG GK gn gN GP gs GS GT h H N p P s S t T \" in \
         *\" ${chars_extra:0:2} \"*) \
           chars_extra=${chars_extra:2}; \
           chars_after=${chars_extra%%\\%*}; \
           ;; \
         *\" ${chars_extra:0:1} \"*) \
           chars_extra=${chars_extra:1}; \
           chars_after=${chars_extra%%\\%*}; \
           ;; \
         *) \
           echo \"No Placeholder found. Probably no tablelike output.\"; \
           continue; \
           ;; \
       esac; \
       if [[ -n \"$chars_begin$chars_after\" ]];then \
         len_extra=$(echo \"$chars_begin$chars_after\" | wc -m); \
         col_length[\"$n:$i\"]=$((${col_length[\"$n:$i\"]}+$len_extra-1)); \
       fi; \
     done <<< \"${line#*=format:}$delim\"; \
     i=1; \
   done <<< \"$(echo -e \"${git_log_cmd//\\%n/\\\\n}\")\"; \
   \
   \
   tree_extn=\"${git_log_cmd%\"$char_spec\"*}\"; \
   tree_extn=\"${tree_extn%%$delim*}\"; \
   tree_extn=\"${tree_extn##*$char_spec}\"; \
   case \"$git_log_cmd\" in \
     *\"--simplify-by-decoration\"*) \
       extr=\"--simplify-by-decoration \"; \
       ;& \
     *\"--author-date-order\"*) \
       log_count=\"log --all --graph $extr--author-date-order --pretty=format:$char_spec $tree_extn$char_spec\"; \
       ;; \
     *\"--date-order\"*) \
       log_count=\"log --all --graph $extr--date-order --pretty=format:$char_spec $tree_extn$char_spec\"; \
       ;; \
     *\"--topo-order\"*) \
       log_count=\"log --all --graph $extr--topo-order --pretty=format:$char_spec $tree_extn$char_spec\"; \
       ;; \
     *) \
       log_count=\"log --all --graph $extr--pretty=format:$char_spec $tree_extn$char_spec\"; \
       ;; \
   esac; \
   col_length[\"1:1\"]=$(eval git \"$log_count\" | wc -L); \
   \
   \
   i=0; \
   while IFS=\"$delim\" read -r graph rest;do \
     ((i++)); \
     graph_line[$i]=\"$graph\"; \
   done < <(eval git \"${git_log_cmd/ --color}\" && echo); \
   \
   \
   i=0; \
   l=0; \
   msg_err=; \
   color_list_ind=-1; \
   color_list_num=${#color_list[*]}; \
   color_repeat_ind=1; \
   while IFS= read -r line;do \
     ((i++)); \
     j=-1; \
     graph_colored=; \
     graph_line_last=\"${graph_line[$i-1]}\"; \
     graph_line=\"${graph_line[$i]}\"; \
     graph_line_next=\"${graph_line[$i+1]}\"; \
     while IFS= read -r char;do \
       ((j++)); \
       case \"$char\" in \
         [^\\ \\_\\*\\/\\|\\\\]) \
           graph_colored=\"${graph_colored}\\033[${point_color}m$char\\033[0m\"; \
           ;; \
         \" \") \
           graph_colored=\"${graph_colored}$char\"; \
           case \"$char_last\" in \
             \" \") \
               unset color_ind[$j]; \
               ;; \
           esac; \
           ;; \
         \"*\") \
           case \"${graph_line_last:$j:1}\" in \
             \"*\") \
               :; \
               ;; \
             \"|\") \
               case \"${graph_line_last:$(($j-1)):1}\" in \
                 \"\\\\\") \
                   color_ind[$j]=${color_ind_last[$j-1]:-${color_ind[$j-1]}}; \
                   ;; \
                 *) \
                   :; \
                   ;; \
               esac; \
               ;; \
             \" \") \
               case \"${graph_line_last:$(($j-1)):1}\" in \
                 \"\\\\\") \
                   color_ind[$j]=${color_ind_last[$j-1]:-${color_ind[$j-1]}}; \
                   ;; \
                 \"/\") \
                   case \"${graph_line_last:$(($j+1)):1}\" in \
                     \"/\") \
                       color_ind[$j]=${color_ind[$j+1]}; \
                       ;; \
                     \" \") \
                       new_col_ind=${#color[*]}; \
                       while true;do \
                         ((color_list_ind++)); \
                         [[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
                         [[ $color_list_ind -ge $color_list_num ]] && break; \
                         new_color=${color_list[$color_list_ind]}; \
                         case \"$new_color\" in \
                           \"\"|[\\ ]*) \
                             continue; \
                             ;; \
                           \"${color[${color_ind[$j-1]}]}\") \
                             [[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
                             ;;& \
                           *) \
                             color[$new_col_ind]=$new_color; \
                             color_ind[$j]=$new_col_ind; \
                             last_new_colored_line=$i; \
                             break; \
                             ;; \
                         esac 2>/dev/null; \
                       done; \
                       ;; \
                     *) \
                       [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                       ;; \
                   esac; \
                   ;; \
                 \" \") \
                   case \"${graph_line_last:$(($j+1)):1}\" in \
                     \"/\") \
                       color_ind[$j]=${color_ind[$j+1]}; \
                       ;; \
                     *) \
                       new_col_ind=${#color[*]}; \
                       while true;do \
                         ((color_list_ind++)); \
                         [[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
                         [[ $color_list_ind -ge $color_list_num ]] && break; \
                         new_color=${color_list[$color_list_ind]}; \
                         case \"$new_color\" in \
                           \"\"|[\\ ]*) \
                             continue; \
                             ;; \
                           \"${color[${color_ind[$j-1]}]}\") \
                             [[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
                             ;;& \
                           *) \
                             color[$new_col_ind]=$new_color; \
                             color_ind[$j]=$new_col_ind; \
                             last_new_colored_line=$i; \
                             break; \
                             ;; \
                         esac 2>/dev/null; \
                       done; \
                       ;; \
                   esac; \
                   ;; \
                 *) \
                   [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                   ;; \
               esac; \
               ;; \
             \"\"|[^\\ \\_\\*\\/\\|\\\\]) \
               new_col_ind=${#color[*]}; \
               while true;do \
                 ((color_list_ind++)); \
                 [[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
                 [[ $color_list_ind -ge $color_list_num ]] && break; \
                 new_color=${color_list[$color_list_ind]}; \
                 case \"$new_color\" in \
                   \"\"|[\\ ]*) \
                     continue; \
                     ;; \
                   \"${color[${color_ind[$j-1]}]}\") \
                     [[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
                     ;;& \
                   *) \
                     color[$new_col_ind]=$new_color; \
                     color_ind[$j]=$new_col_ind; \
                     last_new_colored_line=$i; \
                     break; \
                     ;; \
                 esac 2>/dev/null; \
               done; \
               ;; \
             *) \
               [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
               ;; \
           esac; \
           graph_colored=\"${graph_colored}\\033[${color[${color_ind[$j]}]}m$char\\033[0m\"; \
           point_color=${color[${color_ind[$j]}]}; \
           ;; \
         \"|\") \
           case \"${graph_line_last:$j:1}\" in \
             \" \") \
               case \"${graph_line_last:$(($j-1)):1}\" in \
                 \"/\") \
                   color_ind[$j]=${color_ind[$j+1]}; \
                   ;; \
                 \"\\\\\") \
                   color_ind[$j]=${color_ind_last[$j-1]:-${color_ind[$j-1]}}; \
                   ;; \
                 *) \
                   case \"${graph_line_last:$(($j+1)):1}\" in \
                     \"/\") \
                       color_ind[$j]=${color_ind[$j+1]}; \
                       ;; \
                     *) \
                       [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                       ;; \
                   esac; \
                   ;; \
               esac; \
               ;; \
             \"|\") \
               case \"${graph_line_last:$(($j-1)):1}\" in \
                 \"\\\\\") \
                   case \"${graph_line:$(($j+1)):1}\" in \
                     \"\\\\\") \
                        :; \
                        ;; \
                     \" \") \
                       color_ind[$j]=${color_ind_last[$j-1]}; \
                       ;; \
                     *) \
                       [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                       ;; \
                   esac; \
                   ;; \
                 *) \
                   :; \
                   ;; \
               esac; \
               ;; \
             \"*\") \
               case \"${graph_line:$(($j-1)):1}\" in \
                 \"/\") \
                   if [[ $last_new_colored_line -eq $(($i-1)) ]];then \
                     new_col_ind=${#color[*]}; \
                     while true;do \
                       ((color_list_ind++)); \
                       [[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
                       [[ $color_list_ind -ge $color_list_num ]] && break; \
                       new_color=${color_list[$color_list_ind]}; \
                       case \"$new_color\" in \
                         \"\"|[\\ ]*) \
                           continue; \
                           ;; \
                         \"${color[${color_ind[$j-1]}]}\") \
                           [[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
                           ;;& \
                         *) \
                           color[$new_col_ind]=$new_color; \
                           color_ind[$j]=$new_col_ind; \
                           break; \
                           ;; \
                       esac 2>/dev/null; \
                     done; \
                   else \
                     color_ind[$j]=${color_ind_last[$j]}; \
                   fi; \
                   ;; \
                 *) \
                   :; \
                   ;; \
               esac; \
               ;; \
             \"/\") \
               color_ind[$j]=${color_ind[$j]}; \
               ;; \
             *) \
               [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
               ;; \
           esac; \
           graph_colored=\"${graph_colored}\\033[${color[${color_ind[$j]}]}m$char\\033[0m\"; \
           ;; \
         \"/\") \
           case \"${graph_line_last:$(($j)):1}\" in \
             \"|\") \
               case \"${graph_line_last:$(($j+1)):1}\" in \
                 \"/\") \
                   case \"${graph_line_next:$j:1}\" in \
                     \"|\") \
                       color_ind[$j]=${color_ind[$j+1]}; \
                       ;; \
                     \" \") \
                       color_ind[$j]=${color_ind[$j]}; \
                       ;; \
                     *) \
                       [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                       ;; \
                   esac; \
                   ;; \
                 *) \
                   color_ind[$j]=${color_ind[$j]}; \
                   ;; \
               esac; \
               ;; \
             *) \
               case \"${graph_line_last:$(($j+2)):1}\" in \
                 \"/\"|\"_\") \
                   color_ind[$j]=${color_ind[$j+2]}; \
                   ;; \
                 *) \
                   case \"${graph_line_last:$(($j+1)):1}\" in \
                     \"/\"|\"_\"|\"|\") \
                       color_ind[$j]=${color_ind[$j+1]}; \
                       ;; \
                     \"*\") \
                       case \"${graph_line:$(($j+1)):1}\" in \
                         \"|\") \
                           if [[ $last_new_colored_line -eq $(($i-1)) ]];then \
                             color_ind[$j]=${color_ind_last[$j+1]}; \
                           else \
                             new_col_ind=${#color[*]}; \
                             while true;do \
                               ((color_list_ind++)); \
                               [[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
                               [[ $color_list_ind -ge $color_list_num ]] && break; \
                               new_color=${color_list[$color_list_ind]}; \
                               case \"$new_color\" in \
                                 \"\"|[\\ ]*) \
                                   continue; \
                                   ;; \
                                 \"${color[${color_ind[$j-1]}]}\") \
                                   [[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
                                   ;;& \
                                 *) \
                                   color[$new_col_ind]=$new_color; \
                                   color_ind[$j]=$new_col_ind; \
                                   break; \
                                   ;; \
                               esac 2>/dev/null; \
                             done; \
                           fi; \
                           ;; \
                         *) \
                           color_ind[$j]=${color_ind_last[$j+1]}; \
                           ;; \
                       esac; \
                       ;; \
                     *) \
                       case \"${graph_line_last:$j:1}\" in \
                         \"\\\\\") \
                           :; \
                           ;; \
                         \" \") \
                           case \"${graph_line_last:$(($j+1)):1}\" in \
                             \"*\") \
                               color_ind[$j]=${color_ind[$j+1]}; \
                               ;; \
                             *) \
                               [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                               ;; \
                           esac; \
                           ;; \
                         *) \
                           [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                           ;; \
                       esac; \
                       ;; \
                   esac; \
                   ;; \
               esac; \
               ;; \
           esac; \
           graph_colored=\"${graph_colored}\\033[${color[${color_ind[$j]}]}m$char\\033[0m\"; \
           ;; \
         \"\\\\\") \
           case \"${graph_line_last:$(($j-1)):1}\" in \
             \"|\"|\"\\\\\") \
               color_ind[$j]=${color_ind_last[$j-1]:-${color_ind[$j-1]}}; \
               ;; \
             \"*\") \
               new_col_ind=${#color[*]}; \
               while true;do \
                 ((color_list_ind++)); \
                 [[ $color_list_ind -ge $color_list_num ]] && color_list_ind=$color_repeat_ind; \
                 [[ $color_list_ind -ge $color_list_num ]] && break; \
                 new_color=${color_list[$color_list_ind]}; \
                 case \"$new_color\" in \
                   \"\"|[\\ ]*) \
                     continue; \
                     ;; \
                   \"${color[${color_ind[$j-1]}]}\") \
                     [[ $(($color_list_num-$color_repeat_ind)) -gt 1 ]] && continue; \
                     ;;& \
                   *) \
                     color[$new_col_ind]=$new_color; \
                     color_ind[$j]=$new_col_ind; \
                     break; \
                     ;; \
                 esac 2>/dev/null; \
               done; \
               ;; \
             \" \") \
               case \"${graph_line_last:$(($j-2)):1}\" in \
                 \"\\\\\"|\"_\") \
                   color_ind[$j]=${color_ind_last[$j-2]:-${color_ind[$j-2]}}; \
                   ;; \
                 *) \
                   case \"${graph_line_last:$j:1}\" in \
                     \"|\") \
                       color_ind[$j]=${color_ind_last[$j]:-${color_ind[$j]}}; \
                       ;; \
                     *) \
                       [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                       ;; \
                   esac; \
                   ;; \
               esac; \
               ;; \
             *) \
               [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
               ;; \
           esac; \
           graph_colored=\"${graph_colored}\\033[${color[${color_ind[$j]}]}m$char$char\\033[0m\"; \
           ;; \
         \"_\") \
           case \"${graph_line:$(($j-2)):1}\" in \
             \"\\\\\"|\"_\") \
               color_ind[$j]=${color_ind[$j-2]}; \
               ;; \
             \" \"|\"/\") \
               k=2; \
               while [[ \"${graph_line:$(($j+$k)):1}\" = \"_\" ]];do \
                 k=$(($k+2)); \
               done; \
               case \"${graph_line:$(($j+$k)):1}\" in \
                 \"/\") \
                   case \"${graph_line_last:$(($j+$k+1)):1}\" in \
                     \"*\") \
                       color_ind[$j]=${color_ind[$j+$k+1]}; \
                       ;; \
                     \" \") \
                       case \"${graph_line_last:$(($j+$k)):1}\" in \
                         \"\\\\\") \
                           color_ind[$j]=${color_ind[$j+$k]}; \
                           ;; \
                         *) \
                           [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                           ;; \
                       esac; \
                       ;; \
                     \"|\") \
                       case \"${graph_line:$(($j+$k+1)):1}\" in \
                         \"|\") \
                           color_ind[$j]=${color_ind[$j+$k+2]}; \
                           ;; \
                         \" \") \
                           color_ind[$j]=${color_ind[$j+$k+1]}; \
                           ;; \
                         *) \
                           [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                           ;; \
                       esac; \
                       ;; \
                     *) \
                       [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                       ;; \
                   esac; \
                   ;; \
                 *) \
                   [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
                   ;; \
               esac; \
               ;; \
             *) \
               [[ -n \"$msg_err\" ]] && echo -e \"Unknown case in graph_line $i: $graph_line for char $char at position $j\nwith the former graph_line $(($i-1)): $graph_line_last\"; \
               ;; \
           esac; \
           graph_colored=\"${graph_colored}\\033[${color[${color_ind[$j]}]}m$char\\033[0m\"; \
           ;; \
       esac; \
       char_last=$char; \
     done <<< \"$(grep -Eo \".\" <<< \"${graph_line%%$delim*}\")\"; \
     for key in ${!color_ind[*]};do \
       color_ind_last[$key]=${color_ind[$key]}; \
     done; \
     \
     \
     c=0; \
     ((l++)); \
     [[ $l -gt $n ]] && l=1; \
     while IFS= read -d\"$delim\" -r col_content;do \
       ((c++)); \
       [[ $c -le $graph_col ]] && c_corr=-1 || c_corr=0; \
       if [[ $c -eq 1 ]];then \
         [[ \"${col_content/\\*}\" = \"$col_content\" ]] && [[ $l -eq 1 ]] && l=$n; \
         whitespaces=$(seq -s\" \" $((${col_length[\"1:1\"]}-$j))|tr -d \"[:digit:]\"); \
         col_content[$graph_col]=\"${graph_colored}$whitespaces\"; \
       elif [[ ${col_colored[\"$l:$c\"]:-0} -eq 0 ]];then \
         col_content[$c+$c_corr]=\"\\033[${point_color:-0}m$(printf \"%-${col_length[\"$l:$c\"]}s\" \"${col_content:-\"\"}\")\\033[0m\"; \
       else \
         col_content[$c+$c_corr]=\"$(printf \"%-${col_length[\"$l:$c\"]}s\" \"${col_content:-\"\"}\")\"; \
       fi; \
     done <<< \"$line$delim\"; \
     for ((k=$c+1;k<=$i_max;k++));do \
       [[ $k -le $graph_col ]] && c_corr=-1 || c_corr=0; \
       col_content[$k+$c_corr]=\"$(printf \"%-${col_length[\"$l:$k\"]:-${col_length[\"${last[$k]:-1}:$k\"]:-0}}s\" \"\")\"; \
     done; \
     unset col_content[0]; \
     echo -e \"${col_content[*]}\"; \
     unset col_content[*]; \
   done < <(git $1 && echo); \
 "' "git-colored"

Пояснения:

  • Первый абзац загружает разделитель (iter), список цветов и YourLogAlias ​​в переменные оболочки.
  • Второй считывает длину каждого столбца
  • Третий считает макс. длина дерева
  • Четвертый загружает дерево в массив
  • Пятый раскрашивает дерево на основе анализа случаев
  • Шестой раскрашивает столбцы, не являющиеся древовидными, и выводит выходные данные в виде таблицы.

Самая большая часть - это анализ случая для установки цветов дерева. Другие части объяснены в моем связанном ответе для выходных данных оболочки в виде таблицы.

GitGraph

Создает представление PNG или SVG истории коммитов вашего репозитория Git.

https://code.google.com/p/gitgraph

git -c core.pager='less -SRF' log --oneline --graph --decorate

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

пример вывода

Я установил псевдоним для быстрого доступа, так как команда немного громоздкая.

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

  • Перейдите к графическому представлению вашего хранилища, например, https://gitlab.com/gitlab-org/gitter/webapp/network/develop

  • Прокрутите график вниз до дна (это ленивые загрузки фиксирует!)

  • Используйте инспектор вашего браузера, чтобы скопировать элемент SVG в новый файл

  • Откройте его в выбранном вами рендерере, например Inkscape

Попробуйте Дитаа. Он может преобразовать любую диаграмму ASCII в изображение. Хотя он не был разработан с учетом веток Git, я был впечатлен результатами.

Источник (текстовый файл):

        +--------+
        | hotfix |
        +---+----+
            |
--*<---*<---*
       ^ 
       |
       \--*<---*
               |
           +---+----+
           | master |
           +--------+

Команда:

java -jar ditaa0_9.jar ascii-graph.txt

Результат:

Он также поддерживает фоновые цвета, пунктирные линии, различные формы и многое другое. Смотрите примеры.

Некоторые псевдонимы в ~/.oh-my-zsh/plugins/git/git.plugin.zsh

gke='\gitk --all $(git log -g --pretty=%h)'
glg='git log --stat'
glgg='git log --graph'
glgga='git log --graph --decorate --all'
glgm='git log --graph --max-count=10'
glgp='git log --stat -p'
glo='git log --oneline --decorate'
glog='git log --oneline --decorate --graph'
gloga='git log --oneline --decorate --graph --all'
glol='git log --graph --pretty='\''%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'\'' --abbrev-commit'
glola='git log --graph --pretty='\''%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'\'' --abbrev-commit --all'

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

      git config --global alias.ls '!f() { git log $1 --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cgreen\\ [%ae,%ar]" --decorate --graph; }; f'

Применение:

      # shows commits graph on the current branch
git ls

# shows commits graph on the develop branch
git ls develop 

Вот вид графика:

Другие вопросы по тегам