Skip to content

Commit 97658d4

Browse files
HaraldNordgrengitster
authored andcommitted
stash: add --label-ours, --label-theirs, --label-base for apply
Allow callers of "git stash apply" to pass custom labels for conflict markers instead of the default "Updated upstream" and "Stashed changes". Document the new options and add a test. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent b15384c commit 97658d4

4 files changed

Lines changed: 57 additions & 12 deletions

File tree

Documentation/git-stash.adoc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ git stash list [<log-options>]
1212
git stash show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]
1313
git stash drop [-q | --quiet] [<stash>]
1414
git stash pop [--index] [-q | --quiet] [<stash>]
15-
git stash apply [--index] [-q | --quiet] [<stash>]
15+
git stash apply [--index] [-q | --quiet] [--label-ours=<label>] [--label-theirs=<label>] [--label-base=<label>] [<stash>]
1616
git stash branch <branchname> [<stash>]
1717
git stash [push] [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
1818
[-u | --include-untracked] [-a | --all] [(-m | --message) <message>]
@@ -195,6 +195,15 @@ the index's ones. However, this can fail, when you have conflicts
195195
(which are stored in the index, where you therefore can no longer
196196
apply the changes as they were originally).
197197
198+
`--label-ours=<label>`::
199+
`--label-theirs=<label>`::
200+
`--label-base=<label>`::
201+
These options are only valid for the `apply` command.
202+
+
203+
Use the given labels in conflict markers instead of the default
204+
"Updated upstream", "Stashed changes", and "Stash base".
205+
`--label-base` only has an effect with merge.conflictStyle=diff3.
206+
198207
`-k`::
199208
`--keep-index`::
200209
`--no-keep-index`::

builtin/stash.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
#define BUILTIN_STASH_POP_USAGE \
4545
N_("git stash pop [--index] [-q | --quiet] [<stash>]")
4646
#define BUILTIN_STASH_APPLY_USAGE \
47-
N_("git stash apply [--index] [-q | --quiet] [<stash>]")
47+
N_("git stash apply [--index] [-q | --quiet] [--label-ours=<label>] [--label-theirs=<label>] [--label-base=<label>] [<stash>]")
4848
#define BUILTIN_STASH_BRANCH_USAGE \
4949
N_("git stash branch <branchname> [<stash>]")
5050
#define BUILTIN_STASH_STORE_USAGE \
@@ -591,7 +591,9 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
591591
}
592592

593593
static int do_apply_stash(const char *prefix, struct stash_info *info,
594-
int index, int quiet)
594+
int index, int quiet,
595+
const char *label_ours, const char *label_theirs,
596+
const char *label_base)
595597
{
596598
int clean, ret;
597599
int has_index = index;
@@ -643,9 +645,9 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
643645

644646
init_ui_merge_options(&o, the_repository);
645647

646-
o.branch1 = "Updated upstream";
647-
o.branch2 = "Stashed changes";
648-
o.ancestor = "Stash base";
648+
o.branch1 = label_ours ? label_ours : "Updated upstream";
649+
o.branch2 = label_theirs ? label_theirs : "Stashed changes";
650+
o.ancestor = label_base ? label_base : "Stash base";
649651

650652
if (oideq(&info->b_tree, &c_tree))
651653
o.branch1 = "Version stash was based on";
@@ -723,11 +725,18 @@ static int apply_stash(int argc, const char **argv, const char *prefix,
723725
int ret = -1;
724726
int quiet = 0;
725727
int index = use_index;
728+
const char *label_ours = NULL, *label_theirs = NULL, *label_base = NULL;
726729
struct stash_info info = STASH_INFO_INIT;
727730
struct option options[] = {
728731
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
729732
OPT_BOOL(0, "index", &index,
730733
N_("attempt to recreate the index")),
734+
OPT_STRING(0, "label-ours", &label_ours, N_("label"),
735+
N_("label for the upstream side in conflict markers")),
736+
OPT_STRING(0, "label-theirs", &label_theirs, N_("label"),
737+
N_("label for the stashed side in conflict markers")),
738+
OPT_STRING(0, "label-base", &label_base, N_("label"),
739+
N_("label for the base in diff3 conflict markers")),
731740
OPT_END()
732741
};
733742

@@ -737,7 +746,8 @@ static int apply_stash(int argc, const char **argv, const char *prefix,
737746
if (get_stash_info(&info, argc, argv))
738747
goto cleanup;
739748

740-
ret = do_apply_stash(prefix, &info, index, quiet);
749+
ret = do_apply_stash(prefix, &info, index, quiet,
750+
label_ours, label_theirs, label_base);
741751
cleanup:
742752
free_stash_info(&info);
743753
return ret;
@@ -836,7 +846,8 @@ static int pop_stash(int argc, const char **argv, const char *prefix,
836846
if (get_stash_info_assert(&info, argc, argv))
837847
goto cleanup;
838848

839-
if ((ret = do_apply_stash(prefix, &info, index, quiet)))
849+
if ((ret = do_apply_stash(prefix, &info, index, quiet,
850+
NULL, NULL, NULL)))
840851
printf_ln(_("The stash entry is kept in case "
841852
"you need it again."));
842853
else
@@ -877,7 +888,8 @@ static int branch_stash(int argc, const char **argv, const char *prefix,
877888
strvec_push(&cp.args, oid_to_hex(&info.b_commit));
878889
ret = run_command(&cp);
879890
if (!ret)
880-
ret = do_apply_stash(prefix, &info, 1, 0);
891+
ret = do_apply_stash(prefix, &info, 1, 0,
892+
NULL, NULL, NULL);
881893
if (!ret && info.is_stash_ref)
882894
ret = do_drop_stash(&info, 0);
883895

t/t3903-stash.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ setup_stash() {
5656
git add other-file &&
5757
test_tick &&
5858
git commit -m initial &&
59+
git tag initial &&
5960
echo 2 >file &&
6061
git add file &&
6162
echo 3 >file &&
@@ -1790,4 +1791,27 @@ test_expect_success 'stash.index=false overridden by --index' '
17901791
test_cmp expect file
17911792
'
17921793

1794+
test_expect_success 'apply with custom conflict labels' '
1795+
git reset --hard initial &&
1796+
test_commit label-base conflict-file base-content &&
1797+
echo stashed >conflict-file &&
1798+
git stash push -m "stashed" &&
1799+
test_commit label-upstream conflict-file upstream-content &&
1800+
test_must_fail git -c merge.conflictStyle=diff3 stash apply --label-ours=UP --label-theirs=STASH &&
1801+
test_grep "^<<<<<<< UP" conflict-file &&
1802+
test_grep "^||||||| Stash base" conflict-file &&
1803+
test_grep "^>>>>>>> STASH" conflict-file
1804+
'
1805+
1806+
test_expect_success 'apply with empty conflict labels' '
1807+
git reset --hard initial &&
1808+
test_commit empty-label-base conflict-file base-content &&
1809+
echo stashed >conflict-file &&
1810+
git stash push -m "stashed" &&
1811+
test_commit empty-label-upstream conflict-file upstream-content &&
1812+
test_must_fail git stash apply --label-ours= --label-theirs= &&
1813+
test_grep "^<<<<<<<$" conflict-file &&
1814+
test_grep "^>>>>>>>$" conflict-file
1815+
'
1816+
17931817
test_done

xdiff/xmerge.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,9 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
199199
int size, int i, int style,
200200
xdmerge_t *m, char *dest, int marker_size)
201201
{
202-
int marker1_size = (name1 ? strlen(name1) + 1 : 0);
203-
int marker2_size = (name2 ? strlen(name2) + 1 : 0);
204-
int marker3_size = (name3 ? strlen(name3) + 1 : 0);
202+
int marker1_size = (name1 && *name1 ? strlen(name1) + 1 : 0);
203+
int marker2_size = (name2 && *name2 ? strlen(name2) + 1 : 0);
204+
int marker3_size = (name3 && *name3 ? strlen(name3) + 1 : 0);
205205
int needs_cr = is_cr_needed(xe1, xe2, m);
206206

207207
if (marker_size <= 0)

0 commit comments

Comments
 (0)