Merge branch 'ak/color-decorate-symbols' into seen

A new config for coloring.

* ak/color-decorate-symbols:
  log: add color.decorate.pseudoref config variable
  refs: exempt pseudorefs from pattern prefixing
  refs: add pseudorefs array and iteration functions
  log: add color.decorate.ref config variable
  log: add color.decorate.symbol config variable
  log: use designated inits for decoration_colors
  config: restructure color.decorate documentation
This commit is contained in:
Junio C Hamano
2023-11-17 13:45:59 +09:00
9 changed files with 192 additions and 67 deletions

View File

@ -74,10 +74,34 @@ color.diff.<slot>::
`oldBold`, and `newBold` (see linkgit:git-range-diff[1] for details).
color.decorate.<slot>::
Use customized color for 'git log --decorate' output. `<slot>` is one
of `branch`, `remoteBranch`, `tag`, `stash` or `HEAD` for local
branches, remote-tracking branches, tags, stash and HEAD, respectively
and `grafted` for grafted commits.
Use customized color for the output of 'git log --decorate' as well as
the `%d`, `%D` and `%(decorate)` placeholders in custom log formats,
whereby `<slot>` specifies which decoration elements the color applies
to:
+
--
`HEAD`;;
the current HEAD
`branch`;;
local branches
`remoteBranch`;;
remote-tracking branches
`tag`;;
lightweight and annotated tags
`stash`;;
the stash ref
`ref`;;
any other refs (not shown by default)
`pseudoref`;;
pseudorefs such as ORIG_HEAD or MERGE_HEAD (not shown by default)
`grafted`;;
grafted and replaced commits
`symbol`;;
punctuation symbols surrounding the other elements
--
+
(Variable `log.initialDecorationSet` or linkgit:git-log[1] option
`--clear-decorations` can be used to show all refs and pseudorefs.)
color.grep::
When set to `always`, always highlight matches. When `false` (or

View File

@ -54,8 +54,11 @@ enum decoration_type {
DECORATION_REF_REMOTE,
DECORATION_REF_TAG,
DECORATION_REF_STASH,
DECORATION_REF,
DECORATION_REF_HEAD,
DECORATION_REF_PSEUDO,
DECORATION_GRAFTED,
DECORATION_SYMBOL,
};
void add_name_decoration(enum decoration_type type, const char *name, struct object *obj);

View File

@ -34,13 +34,16 @@ static int decoration_loaded;
static int decoration_flags;
static char decoration_colors[][COLOR_MAXLEN] = {
GIT_COLOR_RESET,
GIT_COLOR_BOLD_GREEN, /* REF_LOCAL */
GIT_COLOR_BOLD_RED, /* REF_REMOTE */
GIT_COLOR_BOLD_YELLOW, /* REF_TAG */
GIT_COLOR_BOLD_MAGENTA, /* REF_STASH */
GIT_COLOR_BOLD_CYAN, /* REF_HEAD */
GIT_COLOR_BOLD_BLUE, /* GRAFTED */
[DECORATION_NONE] = GIT_COLOR_RESET,
[DECORATION_REF_LOCAL] = GIT_COLOR_BOLD_GREEN,
[DECORATION_REF_REMOTE] = GIT_COLOR_BOLD_RED,
[DECORATION_REF_TAG] = GIT_COLOR_BOLD_YELLOW,
[DECORATION_REF_STASH] = GIT_COLOR_BOLD_MAGENTA,
[DECORATION_REF] = GIT_COLOR_BOLD_MAGENTA,
[DECORATION_REF_HEAD] = GIT_COLOR_BOLD_CYAN,
[DECORATION_REF_PSEUDO] = GIT_COLOR_BOLD_CYAN,
[DECORATION_GRAFTED] = GIT_COLOR_BOLD_BLUE,
[DECORATION_SYMBOL] = GIT_COLOR_NIL,
};
static const char *color_decorate_slots[] = {
@ -48,8 +51,11 @@ static const char *color_decorate_slots[] = {
[DECORATION_REF_REMOTE] = "remoteBranch",
[DECORATION_REF_TAG] = "tag",
[DECORATION_REF_STASH] = "stash",
[DECORATION_REF] = "ref",
[DECORATION_REF_HEAD] = "HEAD",
[DECORATION_REF_PSEUDO] = "pseudoref",
[DECORATION_GRAFTED] = "grafted",
[DECORATION_SYMBOL] = "symbol",
};
static const char *decorate_get_color(int decorate_use_color, enum decoration_type ix)
@ -149,7 +155,7 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,
int i;
struct object *obj;
enum object_type objtype;
enum decoration_type deco_type = DECORATION_NONE;
enum decoration_type deco_type = DECORATION_REF;
struct decoration_filter *filter = (struct decoration_filter *)cb_data;
const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
@ -204,6 +210,27 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,
return 0;
}
static int add_pseudoref_decoration(const char *refname,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
{
struct object *obj;
enum object_type objtype;
struct decoration_filter *filter = (struct decoration_filter *)cb_data;
if (filter && !ref_filter_match(refname, filter))
return 0;
objtype = oid_object_info(the_repository, oid, NULL);
if (objtype < 0)
return 0;
obj = lookup_object_by_type(the_repository, oid, objtype);
add_name_decoration(DECORATION_REF_PSEUDO, refname, obj);
return 0;
}
static int add_graft_decoration(const struct commit_graft *graft,
void *cb_data UNUSED)
{
@ -232,6 +259,7 @@ void load_ref_decorations(struct decoration_filter *filter, int flags)
decoration_loaded = 1;
decoration_flags = flags;
for_each_ref(add_ref_decoration, filter);
for_each_pseudoref(add_pseudoref_decoration, filter);
head_ref(add_ref_decoration, filter);
for_each_commit_graft(add_graft_decoration, filter);
}
@ -312,7 +340,7 @@ void format_decorations(struct strbuf *sb,
{
const struct name_decoration *decoration;
const struct name_decoration *current_and_HEAD;
const char *color_commit, *color_reset;
const char *color_symbol, *color_reset;
const char *prefix = " (";
const char *suffix = ")";
@ -337,7 +365,10 @@ void format_decorations(struct strbuf *sb,
tag = opts->tag;
}
color_commit = diff_get_color(use_color, DIFF_COMMIT);
color_symbol = decorate_get_color(use_color, DECORATION_SYMBOL);
if (color_is_nil(color_symbol))
color_symbol = diff_get_color(use_color, DIFF_COMMIT);
color_reset = decorate_get_color(use_color, DECORATION_NONE);
current_and_HEAD = current_pointed_by_HEAD(decoration);
@ -352,7 +383,7 @@ void format_decorations(struct strbuf *sb,
decorate_get_color(use_color, decoration->type);
if (*prefix) {
strbuf_addstr(sb, color_commit);
strbuf_addstr(sb, color_symbol);
strbuf_addstr(sb, prefix);
strbuf_addstr(sb, color_reset);
}
@ -369,7 +400,7 @@ void format_decorations(struct strbuf *sb,
if (current_and_HEAD &&
decoration->type == DECORATION_REF_HEAD) {
strbuf_addstr(sb, color_commit);
strbuf_addstr(sb, color_symbol);
strbuf_addstr(sb, pointer);
strbuf_addstr(sb, color_reset);
strbuf_addstr(sb, decorate_get_color(use_color, current_and_HEAD->type));
@ -382,7 +413,7 @@ void format_decorations(struct strbuf *sb,
decoration = decoration->next;
}
if (*suffix) {
strbuf_addstr(sb, color_commit);
strbuf_addstr(sb, color_symbol);
strbuf_addstr(sb, suffix);
strbuf_addstr(sb, color_reset);
}

59
refs.c
View File

@ -65,6 +65,21 @@ static unsigned char refname_disposition[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
};
/*
* List of documented pseudorefs. This needs to be kept in sync with the list
* in Documentation/revisions.txt.
*/
static const char *const pseudorefs[] = {
"FETCH_HEAD",
"ORIG_HEAD",
"MERGE_HEAD",
"REBASE_HEAD",
"CHERRY_PICK_HEAD",
"REVERT_HEAD",
"BISECT_HEAD",
"AUTO_MERGE",
};
struct ref_namespace_info ref_namespace[] = {
[NAMESPACE_HEAD] = {
.ref = "HEAD",
@ -550,13 +565,16 @@ void normalize_glob_ref(struct string_list_item *item, const char *prefix,
if (prefix)
strbuf_addstr(&normalized_pattern, prefix);
else if (!starts_with(pattern, "refs/") &&
strcmp(pattern, "HEAD"))
strbuf_addstr(&normalized_pattern, "refs/");
/*
* NEEDSWORK: Special case other symrefs such as REBASE_HEAD,
* MERGE_HEAD, etc.
*/
else if (!starts_with(pattern, "refs/") && strcmp(pattern, "HEAD")) {
int i;
for (i = 0; i < ARRAY_SIZE(pseudorefs); i++)
if (!strcmp(pattern, pseudorefs[i]))
break;
if (i == ARRAY_SIZE(pseudorefs))
strbuf_addstr(&normalized_pattern, "refs/");
}
strbuf_addstr(&normalized_pattern, pattern);
strbuf_strip_suffix(&normalized_pattern, "/");
@ -1549,6 +1567,33 @@ int head_ref(each_ref_fn fn, void *cb_data)
return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data);
}
int refs_for_each_pseudoref(struct ref_store *refs,
each_ref_fn fn, void *cb_data)
{
int i;
for (i = 0; i < ARRAY_SIZE(pseudorefs); i++) {
struct object_id oid;
int flag;
if (refs_resolve_ref_unsafe(refs, pseudorefs[i],
RESOLVE_REF_READING, &oid, &flag)) {
int ret = fn(pseudorefs[i], &oid, flag, cb_data);
if (ret)
return ret;
}
}
return 0;
}
int for_each_pseudoref(each_ref_fn fn, void *cb_data)
{
return refs_for_each_pseudoref(get_main_ref_store(the_repository),
fn, cb_data);
}
struct ref_iterator *refs_ref_iterator_begin(
struct ref_store *refs,
const char *prefix,

5
refs.h
View File

@ -320,6 +320,8 @@ typedef int each_repo_ref_fn(struct repository *r,
*/
int refs_head_ref(struct ref_store *refs,
each_ref_fn fn, void *cb_data);
int refs_for_each_pseudoref(struct ref_store *refs,
each_ref_fn fn, void *cb_data);
int refs_for_each_ref(struct ref_store *refs,
each_ref_fn fn, void *cb_data);
int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
@ -334,6 +336,9 @@ int refs_for_each_remote_ref(struct ref_store *refs,
/* just iterates the head ref. */
int head_ref(each_ref_fn fn, void *cb_data);
/* iterates pseudorefs. */
int for_each_pseudoref(each_ref_fn fn, void *cb_data);
/* iterates all refs. */
int for_each_ref(each_ref_fn fn, void *cb_data);

View File

@ -33,13 +33,13 @@ Date: Mon Jun 26 00:04:00 2006 +0000
Merge branch 'side'
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (FETCH_HEAD, refs/heads/side)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
Side
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000

View File

@ -33,13 +33,13 @@ Date: Mon Jun 26 00:04:00 2006 +0000
Merge branch 'side'
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (FETCH_HEAD, side)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000
Side
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000

View File

@ -927,7 +927,7 @@ test_expect_success 'multiple decorate-refs' '
test_expect_success 'decorate-refs-exclude with glob' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach (HEAD -> main)
Merge-tags-octopus-a-and-octopus-b
Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD)
seventh (tag: seventh)
octopus-b (tag: octopus-b)
octopus-a (tag: octopus-a)
@ -944,7 +944,7 @@ test_expect_success 'decorate-refs-exclude with glob' '
test_expect_success 'decorate-refs-exclude without globs' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach (HEAD -> main)
Merge-tags-octopus-a-and-octopus-b
Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD)
seventh (tag: seventh)
octopus-b (tag: octopus-b, octopus-b)
octopus-a (tag: octopus-a, octopus-a)
@ -961,7 +961,7 @@ test_expect_success 'decorate-refs-exclude without globs' '
test_expect_success 'multiple decorate-refs-exclude' '
cat >expect.decorate <<-\EOF &&
Merge-tag-reach (HEAD -> main)
Merge-tags-octopus-a-and-octopus-b
Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD)
seventh (tag: seventh)
octopus-b (tag: octopus-b)
octopus-a (tag: octopus-a)
@ -1022,10 +1022,12 @@ test_expect_success 'decorate-refs-exclude and simplify-by-decoration' '
EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs-exclude="*octopus*" \
--decorate-refs-exclude="ORIG_HEAD" \
--simplify-by-decoration >actual &&
test_cmp expect.decorate actual &&
git -c log.excludeDecoration="*octopus*" log \
-n6 --decorate=short --pretty="tformat:%f%d" \
git -c log.excludeDecoration="*octopus*" \
-c log.excludeDecoration="ORIG_HEAD" \
log -n6 --decorate=short --pretty="tformat:%f%d" \
--simplify-by-decoration >actual &&
test_cmp expect.decorate actual
'
@ -1067,9 +1069,10 @@ test_expect_success 'decorate-refs and simplify-by-decoration without output' '
test_cmp expect actual
'
test_expect_success 'decorate-refs-exclude HEAD' '
test_expect_success 'decorate-refs-exclude HEAD ORIG_HEAD' '
git log --decorate=full --oneline \
--decorate-refs-exclude="HEAD" >actual &&
--decorate-refs-exclude="HEAD" \
--decorate-refs-exclude="ORIG_HEAD" >actual &&
! grep HEAD actual
'
@ -1107,7 +1110,7 @@ test_expect_success '--clear-decorations overrides defaults' '
cat >expect.all <<-\EOF &&
Merge-tag-reach (HEAD -> refs/heads/main)
Merge-tags-octopus-a-and-octopus-b
Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD)
seventh (tag: refs/tags/seventh)
octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)
octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)
@ -1139,7 +1142,7 @@ test_expect_success '--clear-decorations clears previous exclusions' '
cat >expect.all <<-\EOF &&
Merge-tag-reach (HEAD -> refs/heads/main)
reach (tag: refs/tags/reach, refs/heads/reach)
Merge-tags-octopus-a-and-octopus-b
Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD)
octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)
octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)
seventh (tag: refs/tags/seventh)

View File

@ -17,7 +17,10 @@ test_expect_success setup '
git config color.decorate.remoteBranch red &&
git config color.decorate.tag "reverse bold yellow" &&
git config color.decorate.stash magenta &&
git config color.decorate.ref blue &&
git config color.decorate.pseudoref "bold cyan" &&
git config color.decorate.grafted black &&
git config color.decorate.symbol white &&
git config color.decorate.HEAD cyan &&
c_reset="<RESET>" &&
@ -27,10 +30,14 @@ test_expect_success setup '
c_remoteBranch="<RED>" &&
c_tag="<BOLD;REVERSE;YELLOW>" &&
c_stash="<MAGENTA>" &&
c_ref="<BLUE>" &&
c_pseudoref="<BOLD;CYAN>" &&
c_HEAD="<CYAN>" &&
c_grafted="<BLACK>" &&
c_symbol="<WHITE>" &&
test_commit A &&
git update-ref refs/foo A &&
git clone . other &&
(
cd other &&
@ -41,7 +48,10 @@ test_expect_success setup '
test_commit B &&
git tag v1.0 &&
echo >>A.t &&
git stash save Changes to A.t
git stash save Changes to A.t &&
git reset other/main &&
git reset ORIG_HEAD &&
git revert --no-commit @~
'
cmp_filtered_decorations () {
@ -53,20 +63,24 @@ cmp_filtered_decorations () {
# to this test since it does not contain any decoration, hence --first-parent
test_expect_success 'commit decorations colored correctly' '
cat >expect <<-EOF &&
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\
${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_commit})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A1${c_reset}${c_commit}, \
${c_reset}${c_remoteBranch}other/main${c_reset}${c_commit})${c_reset} A1
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_stash}refs/stash${c_reset}${c_commit})${c_reset} On main: Changes to A.t
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}${c_HEAD}HEAD${c_reset}\
${c_symbol} -> ${c_reset}${c_branch}main${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_symbol})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\
${c_pseudoref}ORIG_HEAD${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A1${c_reset}${c_symbol}, ${c_reset}\
${c_remoteBranch}other/main${c_reset}${c_symbol})${c_reset} A1
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\
${c_stash}refs/stash${c_reset}${c_symbol})${c_reset} On main: Changes to A.t
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\
${c_pseudoref}REVERT_HEAD${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbol}, ${c_reset}\
${c_ref}refs/foo${c_reset}${c_symbol})${c_reset} A
EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always --all >actual &&
git log --first-parent --no-abbrev --decorate --color=always \
--decorate-refs-exclude=FETCH_HEAD --oneline --all >actual &&
cmp_filtered_decorations
'
@ -84,14 +98,14 @@ test_expect_success 'test coloring with replace-objects' '
git replace HEAD~1 HEAD~2 &&
cat >expect <<-EOF &&
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\
${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_commit})${c_reset} D
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}C${c_reset}${c_commit}, \
${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}${c_HEAD}HEAD${c_reset}\
${c_symbol} -> ${c_reset}${c_branch}main${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_symbol})${c_reset} D
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}C${c_reset}${c_symbol}, ${c_reset}\
${c_grafted}replaced${c_reset}${c_symbol})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbol})${c_reset} A
EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&
@ -110,15 +124,15 @@ test_expect_success 'test coloring with grafted commit' '
git replace --graft HEAD HEAD~2 &&
cat >expect <<-EOF &&
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\
${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_commit}, \
${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_commit}, \
${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_commit})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}${c_HEAD}HEAD${c_reset}\
${c_symbol} -> ${c_reset}${c_branch}main${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_symbol}, ${c_reset}\
${c_grafted}replaced${c_reset}${c_symbol})${c_reset} D
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_symbol})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbol})${c_reset} A
EOF
git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&