git:--graph / - root提交的oneline graph标记字符

时间:2017-12-01 10:09:42

标签: git

git具有丰富的日志格式功能,允许以各种方式格式化存储库提交日志。我通常更喜欢--graph--oneline选项,以使历史记录看起来更自然"自然"并使它分别更紧凑。在我的一个存储库中,我使用没有共同父项的分支,因此git log --graph --oneline master orphan产生如下内容:

* 667788 (orphan) Orphan message 1
* 334455 (master) Master message 2
* 001122 (master) Master message 1

提交001122667788是root提交,但它们在视觉上不可识别为根。是否有可能使graph / oneline渲染另一个字符,而不是*,用于root提交,以便它们可以轻松识别?  例如,像

@ 667788 (orphan) Orphan message 1
* 334455 (master) Master message 2
@ 001122 (master) Master message 1

会很棒。有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:1)

这是一个可以或多或少起作用的别名:

x-log = "!f() { \
    git log --graph --no-abbrev-commit $@ \
    | sed 's/* \\(\\x1b\\[[0-9;]*m\\)\\?\\(commit \\)\\?\\('"$(echo -n $(git rev-list --max-parents=0 --no-abbrev-commit --all) | sed 's/ /\\\\|/g')"'\\)/@ \\1\\2\\3/g'; \
}; f"

"实验" log的实施方式如下:

  • 它可以使用bash函数f声明/调用模式接受任意数量的参数。
  • 所有x-log个参数都传递给后台log命令,后者设置图形模式并强制完整提交SHA-1输出,没有缩写。
  • sed模式通常为's/* \(\x1b\[[0-9;]*m\)\?\(commit \)\{0,1\}\('"$(echo -n $(git rev-list --max-parents=0 --no-abbrev-commit --all) | sed 's/ /\\|/g')"'\)/@ \1\2\3/g',但需要双斜杠转义才能作为Git别名:
    • * - 默认图表节点标记。
    • \(\x1b\[[0-9;]*m\)\? - 可选的ANSI转义模式(颜色支持;正则表达式模式来自https://superuser.com/questions/380772/removing-ansi-color-codes-from-text-stream)。
    • \(commit \)\? - 在常规和图表commit结果中显示的可选log
    • \('"$(echo -n $(git rev-list --max-parents=0 --no-abbrev-commit --all) | sed 's/ /\\|/g')"'\) - 这个似乎是&#34的好候选人;它可以用另一种方式完成" (我不知道它是否做得对)。 git rev-list --max-parents=0 --all检索所有root提交的SHA-1哈希值。这些哈希值应通过sed - 转义管道(\|)在一行中连接,而不会有新的尾随行(echo -n做得很好)。
    • @ \1\2\3 - 使用根标记@和上述捕获组呈现输出:\1是可选的ANSI模式,\2是可选的单词&#34 ; commit",\3分别是提交SHA-1哈希。

此别名具有以下限制:

  • 它不适用于缩写提交(因此git x-log --oneline不起作用,因为它暗示--abbrev-commit,除非它明确地用--no-abbrev覆盖,但它可以改进或通过全局修改别名源代码切换到--abbrev-commit
  • 它会禁用默认的寻呼机设置,因为git输出被写入管道以便用sed处理,而不是直接用于stdout。
  • 它还会禁用默认颜色支持。
  • 它严重依赖于regexps。

一些例子:

git x-log --all --color=always

@ commit 411104dcfa8ed1e5c2b09f8ce26971a46ab4e64a
  Author: - <->
  Date:   Sun Dec 17 16:50:26 2017 +0200

      Orphan message 1

* commit a6485cee4bd1d4d8f23e2bd27b3678f40f5b7a26
| Author: - <->
| Date:   Sun Dec 17 16:48:57 2017 +0200
| 
|     Master message 2
| 
@ commit ce45a56a31369e83544adb8c18ee346185ad6380
  Author: - <->
  Date:   Sun Dec 17 16:48:45 2017 +0200

      Master message 1

git x-log --all --oneline --color=always

(没有@个字符,因为此别名仅在no-abbrev-commit处于活动状态时有效,而--abbrev-commit--oneline自动设置)

* 411104d Orphan message 1
* a6485ce Master message 2
* ce45a56 Master message 1

git x-log --all --pretty=oneline --color=always

@ 411104d Orphan message 1
* a6485ce Master message 2
@ ce45a56 Master message 1

我今天在Windows Git安装上测试了它,但我相信它也适用于Linux。 是的,如果Git能够开箱即用,那真的很酷。

答案 1 :(得分:0)

我设法对git进行了一些微小的改动。 新的布尔log.showRootMark配置选项为初始提交启用@指示符。 默认行为保持不变。

git -c log.showRootMark log --graph --oneline

@ 667788 (orphan) Orphan message 1
* 334455 (master) Master message 2
@ 001122 (master) Master message 1

git log --graph --oneline

* 667788 (orphan) Orphan message 1
* 334455 (master) Master message 2
* 001122 (master) Master message 1

补丁(最初置于c2a499e6c31ed613a606ffdeb5bb74ab41e9a586之上):

 Documentation/config.txt  |  5 +++++
 Documentation/git-log.txt |  5 +++++
 graph.c                   | 20 ++++++++++++++++++++
 t/t4202-log.sh            | 16 ++++++++++++++++
 4 files changed, 46 insertions(+)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 4e0cff87f..0a32357e3 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2254,6 +2254,11 @@ log.showRoot::
    Tools like linkgit:git-log[1] or linkgit:git-whatchanged[1], which
    normally hide the root commit will now show it. True by default.

+log.showRootMark::
+   If true, the initial commit in `git log --graph` will be marked
+   with the at sign (`@`). Otherwise the initial commit will be
+   marked with the default asterisk sign (`*`). False by default.
+
 log.showSignature::
    If true, makes linkgit:git-log[1], linkgit:git-show[1], and
    linkgit:git-whatchanged[1] assume `--show-signature`.
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 5437f8b0f..7f5436231 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -205,6 +205,11 @@ log.showRoot::
    `git log -p` output would be shown without a diff attached.
    The default is `true`.

+log.showRootMark::
+   If true, the initial commit in `git log --graph` will be marked
+   with the at sign (`@`). Otherwise the initial commit will be
+   marked with the default asterisk sign (`*`). False by default.
+
 log.showSignature::
    If `true`, `git log` and related commands will act as if the
    `--show-signature` option was passed to them.
diff --git a/graph.c b/graph.c
index e1f6d3bdd..d14ffec7a 100644
--- a/graph.c
+++ b/graph.c
@@ -80,6 +80,7 @@ static void graph_show_line_prefix(const struct diff_options *diffopt)

 static const char **column_colors;
 static unsigned short column_colors_max;
+static int show_root_mark;

 static void parse_graph_colors_config(struct argv_array *colors, const char *string)
 {
@@ -256,6 +257,16 @@ void graph_setup_line_prefix(struct diff_options *diffopt)
 }


+static int git_graph_config(const char *var, const char *value, void *cb)
+{
+   if (!strcmp(var, "log.showrootmark")) {
+       show_root_mark = git_config_bool(var, value);
+       return 0;
+   }
+
+   return git_default_config(var, value, cb);
+}
+
 struct git_graph *graph_init(struct rev_info *opt)
 {
    struct git_graph *graph = xmalloc(sizeof(struct git_graph));
@@ -276,6 +287,7 @@ struct git_graph *graph_init(struct rev_info *opt)
                        custom_colors.argc - 1);
        }
    }
+   git_config(git_graph_config, NULL);

    graph->commit = NULL;
    graph->revs = opt;
@@ -835,6 +847,14 @@ static void graph_output_commit_char(struct git_graph *graph, struct strbuf *sb)
        return;
    }

+   /*
+    * If the commit has no parents, it's a root commit
+    */
+   if (show_root_mark && !graph->num_parents) {
+       strbuf_addch(sb, '@');
+       return;
+   }
+
    /*
     * get_revision_mark() handles all other cases without assert()
     */
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 25b1f8cc7..350e35264 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -455,6 +455,22 @@ test_expect_success 'simple log --graph' '
    test_cmp expect actual
 '

+cat > expect <<EOF
+* Second
+* sixth
+* fifth
+* fourth
+* third
+* second
+@ initial
+EOF
+
+test_expect_success 'simple log --graph' '
+   test_config log.showRootMark true &&
+   git log --graph --pretty=tformat:%s >actual &&
+   test_cmp expect actual
+'
+
 cat > expect <<EOF
 123 * Second
 123 * sixth
-- 
2.16.2

更新#1

这是一个不足够的补丁。这是因为:

  • 基本上,get_revision_mark应该负责返回一个标记,但它似乎无法知道提交图父节点计数(git_graph结构仅在graph.c中声明+必须正确更改)。因此,我似乎无法使其适用于rev-list
  • 此外,该补丁不会引入命令行选项。我没有足够的时间来了解它是如何在Git代码库中完成的。
  • 此修补程序不适用于--left-right(虽然可以轻松实现)。
    • 此案例[]是否足够好?
  • 等:https://marc.info/?l=git&m=152261624606630