Revert "Merge branch 'hn/git-checkout-m-with-stash' into next"
This reverts commitnextb4e5a964fa, reversing changes made to0e6c98f313, as the topic is still getting rerolled.
parent
1d1c64f7a3
commit
af818d6312
|
|
@ -251,19 +251,20 @@ working tree, by copying them from elsewhere, extracting a tarball, etc.
|
|||
are different between the current branch and the branch to
|
||||
which you are switching, the command refuses to switch
|
||||
branches in order to preserve your modifications in context.
|
||||
With this option, the conflicting local changes are
|
||||
automatically stashed before the switch and reapplied
|
||||
afterwards. If the local changes do not overlap with the
|
||||
differences between branches, the switch proceeds without
|
||||
stashing. If reapplying the stash results in conflicts, the
|
||||
entry is saved to the stash list. Resolve the conflicts
|
||||
and run `git stash drop` when done, or clear the working
|
||||
tree (e.g. with `git reset --hard`) before running `git stash
|
||||
pop` later to re-apply your changes.
|
||||
However, with this option, a three-way merge between the current
|
||||
branch, your working tree contents, and the new branch
|
||||
is done, and you will be on the new branch.
|
||||
+
|
||||
When a merge conflict happens, the index entries for conflicting
|
||||
paths are left unmerged, and you need to resolve the conflicts
|
||||
and mark the resolved paths with `git add` (or `git rm` if the merge
|
||||
should result in deletion of the path).
|
||||
+
|
||||
When checking out paths from the index, this option lets you recreate
|
||||
the conflicted merge in the specified paths. This option cannot be
|
||||
used when checking out paths from a tree-ish.
|
||||
+
|
||||
When switching branches with `--merge`, staged changes may be lost.
|
||||
|
||||
`--conflict=<style>`::
|
||||
The same as `--merge` option above, but changes the way the
|
||||
|
|
@ -577,44 +578,39 @@ $ git checkout mytopic
|
|||
error: You have local changes to 'frotz'; not switching branches.
|
||||
------------
|
||||
|
||||
You can give the `-m` flag to the command, which would carry your local
|
||||
changes to the new branch:
|
||||
You can give the `-m` flag to the command, which would try a
|
||||
three-way merge:
|
||||
|
||||
------------
|
||||
$ git checkout -m mytopic
|
||||
Switched to branch 'mytopic'
|
||||
Auto-merging frotz
|
||||
------------
|
||||
|
||||
After the switch, the local modifications are reapplied and are _not_
|
||||
After this three-way merge, the local modifications are _not_
|
||||
registered in your index file, so `git diff` would show you what
|
||||
changes you made since the tip of the new branch.
|
||||
|
||||
=== 3. Merge conflict
|
||||
|
||||
When the `--merge` (`-m`) option is in effect and the locally
|
||||
modified files overlap with files that need to be updated by the
|
||||
branch switch, the changes are stashed and reapplied after the
|
||||
switch. If this process results in conflicts, a stash entry is saved
|
||||
and made available in `git stash list`:
|
||||
When a merge conflict happens during switching branches with
|
||||
the `-m` option, you would see something like this:
|
||||
|
||||
------------
|
||||
$ git checkout -m mytopic
|
||||
Your local changes are stashed, however, applying it to carry
|
||||
forward your local changes resulted in conflicts:
|
||||
|
||||
- You can try resolving them now. If you resolved them
|
||||
successfully, discard the stash entry with "git stash drop".
|
||||
|
||||
- Alternatively you can "git reset --hard" if you do not want
|
||||
to deal with them right now, and later "git stash pop" to
|
||||
recover your local changes.
|
||||
Auto-merging frotz
|
||||
ERROR: Merge conflict in frotz
|
||||
fatal: merge program failed
|
||||
------------
|
||||
|
||||
You can try resolving the conflicts now. Edit the conflicting files
|
||||
and mark them resolved with `git add` as usual, then run `git stash
|
||||
drop` to discard the stash entry. Alternatively, you can clear the
|
||||
working tree with `git reset --hard` and recover your local changes
|
||||
later with `git stash pop`.
|
||||
At this point, `git diff` shows the changes cleanly merged as in
|
||||
the previous example, as well as the changes in the conflicted
|
||||
files. Edit and resolve the conflict and mark it resolved with
|
||||
`git add` as usual:
|
||||
|
||||
------------
|
||||
$ edit frotz
|
||||
$ git add frotz
|
||||
------------
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ git stash list [<log-options>]
|
|||
git stash show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]
|
||||
git stash drop [-q | --quiet] [<stash>]
|
||||
git stash pop [--index] [-q | --quiet] [<stash>]
|
||||
git stash apply [--index] [-q | --quiet] [--label-ours=<label>] [--label-theirs=<label>] [--label-base=<label>] [<stash>]
|
||||
git stash apply [--index] [-q | --quiet] [<stash>]
|
||||
git stash branch <branchname> [<stash>]
|
||||
git stash [push] [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
|
||||
[-u | --include-untracked] [-a | --all] [(-m | --message) <message>]
|
||||
|
|
@ -195,15 +195,6 @@ the index's ones. However, this can fail, when you have conflicts
|
|||
(which are stored in the index, where you therefore can no longer
|
||||
apply the changes as they were originally).
|
||||
|
||||
`--label-ours=<label>`::
|
||||
`--label-theirs=<label>`::
|
||||
`--label-base=<label>`::
|
||||
These options are only valid for the `apply` command.
|
||||
+
|
||||
Use the given labels in conflict markers instead of the default
|
||||
"Updated upstream", "Stashed changes", and "Stash base".
|
||||
`--label-base` only has an effect with merge.conflictStyle=diff3.
|
||||
|
||||
`-k`::
|
||||
`--keep-index`::
|
||||
`--no-keep-index`::
|
||||
|
|
|
|||
|
|
@ -123,19 +123,18 @@ variable.
|
|||
|
||||
`-m`::
|
||||
`--merge`::
|
||||
If you have local modifications to one or more files that
|
||||
are different between the current branch and the branch to
|
||||
which you are switching, the command normally refuses to
|
||||
switch branches in order to preserve your modifications in
|
||||
context. However, with this option, the conflicting local
|
||||
changes are automatically stashed before the switch and
|
||||
reapplied afterwards. If the local changes do not overlap
|
||||
with the differences between branches, the switch proceeds
|
||||
without stashing. If reapplying the stash results in
|
||||
conflicts, the entry is saved to the stash list. Resolve
|
||||
the conflicts and run `git stash drop` when done, or clear
|
||||
the working tree (e.g. with `git reset --hard`) before
|
||||
running `git stash pop` later to re-apply your changes.
|
||||
If you have local modifications to one or more files that are
|
||||
different between the current branch and the branch to which
|
||||
you are switching, the command refuses to switch branches in
|
||||
order to preserve your modifications in context. However,
|
||||
with this option, a three-way merge between the current
|
||||
branch, your working tree contents, and the new branch is
|
||||
done, and you will be on the new branch.
|
||||
+
|
||||
When a merge conflict happens, the index entries for conflicting
|
||||
paths are left unmerged, and you need to resolve the conflicts
|
||||
and mark the resolved paths with `git add` (or `git rm` if the merge
|
||||
should result in deletion of the path).
|
||||
|
||||
`--conflict=<style>`::
|
||||
The same as `--merge` option above, but changes the way the
|
||||
|
|
@ -218,15 +217,15 @@ $ git switch mytopic
|
|||
error: You have local changes to 'frotz'; not switching branches.
|
||||
------------
|
||||
|
||||
You can give the `-m` flag to the command, which would carry your local
|
||||
changes to the new branch:
|
||||
You can give the `-m` flag to the command, which would try a three-way
|
||||
merge:
|
||||
|
||||
------------
|
||||
$ git switch -m mytopic
|
||||
Switched to branch 'mytopic'
|
||||
Auto-merging frotz
|
||||
------------
|
||||
|
||||
After the switch, the local modifications are reapplied and are _not_
|
||||
After this three-way merge, the local modifications are _not_
|
||||
registered in your index file, so `git diff` would show you what
|
||||
changes you made since the tip of the new branch.
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "merge-ll.h"
|
||||
#include "lockfile.h"
|
||||
#include "mem-pool.h"
|
||||
#include "merge-ort-wrappers.h"
|
||||
#include "object-file.h"
|
||||
#include "object-name.h"
|
||||
#include "odb.h"
|
||||
|
|
@ -29,7 +30,6 @@
|
|||
#include "repo-settings.h"
|
||||
#include "resolve-undo.h"
|
||||
#include "revision.h"
|
||||
#include "sequencer.h"
|
||||
#include "setup.h"
|
||||
#include "strvec.h"
|
||||
#include "submodule.h"
|
||||
|
|
@ -790,10 +790,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||
struct tree *new_tree;
|
||||
|
||||
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
|
||||
if (repo_read_index_preload(the_repository, NULL, 0) < 0) {
|
||||
rollback_lock_file(&lock_file);
|
||||
if (repo_read_index_preload(the_repository, NULL, 0) < 0)
|
||||
return error(_("index file corrupt"));
|
||||
}
|
||||
|
||||
resolve_undo_clear_index(the_repository->index);
|
||||
if (opts->new_orphan_branch && opts->orphan_from_empty_tree) {
|
||||
|
|
@ -806,18 +804,14 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||
} else {
|
||||
new_tree = repo_get_commit_tree(the_repository,
|
||||
new_branch_info->commit);
|
||||
if (!new_tree) {
|
||||
rollback_lock_file(&lock_file);
|
||||
if (!new_tree)
|
||||
return error(_("unable to read tree (%s)"),
|
||||
oid_to_hex(&new_branch_info->commit->object.oid));
|
||||
}
|
||||
}
|
||||
if (opts->discard_changes) {
|
||||
ret = reset_tree(new_tree, opts, 1, writeout_error, new_branch_info);
|
||||
if (ret) {
|
||||
rollback_lock_file(&lock_file);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
struct tree_desc trees[2];
|
||||
struct tree *tree;
|
||||
|
|
@ -827,7 +821,6 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||
refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, NULL);
|
||||
|
||||
if (unmerged_index(the_repository->index)) {
|
||||
rollback_lock_file(&lock_file);
|
||||
error(_("you need to resolve your current index first"));
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -860,8 +853,82 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
|||
ret = unpack_trees(2, trees, &topts);
|
||||
clear_unpack_trees_porcelain(&topts);
|
||||
if (ret == -1) {
|
||||
rollback_lock_file(&lock_file);
|
||||
return 1;
|
||||
/*
|
||||
* Unpack couldn't do a trivial merge; either
|
||||
* give up or do a real merge, depending on
|
||||
* whether the merge flag was used.
|
||||
*/
|
||||
struct tree *work;
|
||||
struct tree *old_tree;
|
||||
struct merge_options o;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
struct strbuf old_commit_shortname = STRBUF_INIT;
|
||||
|
||||
if (!opts->merge)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Without old_branch_info->commit, the below is the same as
|
||||
* the two-tree unpack we already tried and failed.
|
||||
*/
|
||||
if (!old_branch_info->commit)
|
||||
return 1;
|
||||
old_tree = repo_get_commit_tree(the_repository,
|
||||
old_branch_info->commit);
|
||||
|
||||
if (repo_index_has_changes(the_repository, old_tree, &sb))
|
||||
die(_("cannot continue with staged changes in "
|
||||
"the following files:\n%s"), sb.buf);
|
||||
strbuf_release(&sb);
|
||||
|
||||
/* Do more real merge */
|
||||
|
||||
/*
|
||||
* We update the index fully, then write the
|
||||
* tree from the index, then merge the new
|
||||
* branch with the current tree, with the old
|
||||
* branch as the base. Then we reset the index
|
||||
* (but not the working tree) to the new
|
||||
* branch, leaving the working tree as the
|
||||
* merged version, but skipping unmerged
|
||||
* entries in the index.
|
||||
*/
|
||||
|
||||
add_files_to_cache(the_repository, NULL, NULL, NULL, 0,
|
||||
0, 0);
|
||||
init_ui_merge_options(&o, the_repository);
|
||||
o.verbosity = 0;
|
||||
work = write_in_core_index_as_tree(the_repository,
|
||||
the_repository->index);
|
||||
|
||||
ret = reset_tree(new_tree,
|
||||
opts, 1,
|
||||
writeout_error, new_branch_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
o.ancestor = old_branch_info->name;
|
||||
if (!old_branch_info->name) {
|
||||
strbuf_add_unique_abbrev(&old_commit_shortname,
|
||||
&old_branch_info->commit->object.oid,
|
||||
DEFAULT_ABBREV);
|
||||
o.ancestor = old_commit_shortname.buf;
|
||||
}
|
||||
o.branch1 = new_branch_info->name;
|
||||
o.branch2 = "local";
|
||||
o.conflict_style = opts->conflict_style;
|
||||
ret = merge_ort_nonrecursive(&o,
|
||||
new_tree,
|
||||
work,
|
||||
old_tree);
|
||||
if (ret < 0)
|
||||
die(NULL);
|
||||
ret = reset_tree(new_tree,
|
||||
opts, 0,
|
||||
writeout_error, new_branch_info);
|
||||
strbuf_release(&o.obuf);
|
||||
strbuf_release(&old_commit_shortname);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1106,9 +1173,6 @@ static int switch_branches(const struct checkout_opts *opts,
|
|||
struct object_id rev;
|
||||
int flag, writeout_error = 0;
|
||||
int do_merge = 1;
|
||||
int created_autostash = 0;
|
||||
struct strbuf old_commit_shortname = STRBUF_INIT;
|
||||
const char *stash_label_base = NULL;
|
||||
|
||||
trace2_cmd_mode("branch");
|
||||
|
||||
|
|
@ -1146,31 +1210,10 @@ static int switch_branches(const struct checkout_opts *opts,
|
|||
do_merge = 0;
|
||||
}
|
||||
|
||||
if (old_branch_info.name)
|
||||
stash_label_base = old_branch_info.name;
|
||||
else if (old_branch_info.commit) {
|
||||
strbuf_add_unique_abbrev(&old_commit_shortname,
|
||||
&old_branch_info.commit->object.oid,
|
||||
DEFAULT_ABBREV);
|
||||
stash_label_base = old_commit_shortname.buf;
|
||||
}
|
||||
|
||||
if (do_merge) {
|
||||
ret = merge_working_tree(opts, &old_branch_info, new_branch_info, &writeout_error);
|
||||
if (ret && opts->merge) {
|
||||
create_autostash_ref_silent(the_repository,
|
||||
"CHECKOUT_AUTOSTASH_HEAD");
|
||||
created_autostash = 1;
|
||||
ret = merge_working_tree(opts, &old_branch_info, new_branch_info, &writeout_error);
|
||||
}
|
||||
if (ret) {
|
||||
apply_autostash_ref_with_labels(the_repository,
|
||||
"CHECKOUT_AUTOSTASH_HEAD",
|
||||
new_branch_info->name,
|
||||
"local",
|
||||
stash_label_base);
|
||||
branch_info_release(&old_branch_info);
|
||||
strbuf_release(&old_commit_shortname);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -1180,29 +1223,8 @@ static int switch_branches(const struct checkout_opts *opts,
|
|||
|
||||
update_refs_for_switch(opts, &old_branch_info, new_branch_info);
|
||||
|
||||
if (opts->conflict_style >= 0) {
|
||||
struct strbuf cfg = STRBUF_INIT;
|
||||
strbuf_addf(&cfg, "merge.conflictStyle=%s",
|
||||
conflict_style_name(opts->conflict_style));
|
||||
git_config_push_parameter(cfg.buf);
|
||||
strbuf_release(&cfg);
|
||||
}
|
||||
apply_autostash_ref_with_labels(the_repository, "CHECKOUT_AUTOSTASH_HEAD",
|
||||
new_branch_info->name, "local",
|
||||
stash_label_base);
|
||||
|
||||
discard_index(the_repository->index);
|
||||
if (repo_read_index(the_repository) < 0)
|
||||
die(_("index file corrupt"));
|
||||
|
||||
if (created_autostash && !opts->discard_changes && !opts->quiet &&
|
||||
new_branch_info->commit)
|
||||
show_local_changes(&new_branch_info->commit->object,
|
||||
&opts->diff_options);
|
||||
|
||||
ret = post_checkout_hook(old_branch_info.commit, new_branch_info->commit, 1);
|
||||
branch_info_release(&old_branch_info);
|
||||
strbuf_release(&old_commit_shortname);
|
||||
|
||||
return ret || writeout_error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#define BUILTIN_STASH_POP_USAGE \
|
||||
N_("git stash pop [--index] [-q | --quiet] [<stash>]")
|
||||
#define BUILTIN_STASH_APPLY_USAGE \
|
||||
N_("git stash apply [--index] [-q | --quiet] [--label-ours=<label>] [--label-theirs=<label>] [--label-base=<label>] [<stash>]")
|
||||
N_("git stash apply [--index] [-q | --quiet] [<stash>]")
|
||||
#define BUILTIN_STASH_BRANCH_USAGE \
|
||||
N_("git stash branch <branchname> [<stash>]")
|
||||
#define BUILTIN_STASH_STORE_USAGE \
|
||||
|
|
@ -590,11 +590,8 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
|
|||
die(_("could not write index"));
|
||||
}
|
||||
|
||||
static int do_apply_stash_with_labels(const char *prefix,
|
||||
struct stash_info *info,
|
||||
int index, int quiet,
|
||||
const char *label_ours, const char *label_theirs,
|
||||
const char *label_base)
|
||||
static int do_apply_stash(const char *prefix, struct stash_info *info,
|
||||
int index, int quiet)
|
||||
{
|
||||
int clean, ret;
|
||||
int has_index = index;
|
||||
|
|
@ -646,9 +643,9 @@ static int do_apply_stash_with_labels(const char *prefix,
|
|||
|
||||
init_ui_merge_options(&o, the_repository);
|
||||
|
||||
o.branch1 = label_ours ? label_ours : "Updated upstream";
|
||||
o.branch2 = label_theirs ? label_theirs : "Stashed changes";
|
||||
o.ancestor = label_base ? label_base : "Stash base";
|
||||
o.branch1 = "Updated upstream";
|
||||
o.branch2 = "Stashed changes";
|
||||
o.ancestor = "Stash base";
|
||||
|
||||
if (oideq(&info->b_tree, &c_tree))
|
||||
o.branch1 = "Version stash was based on";
|
||||
|
|
@ -720,31 +717,17 @@ restore_untracked:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int do_apply_stash(const char *prefix, struct stash_info *info,
|
||||
int index, int quiet)
|
||||
{
|
||||
return do_apply_stash_with_labels(prefix, info, index, quiet,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int apply_stash(int argc, const char **argv, const char *prefix,
|
||||
struct repository *repo UNUSED)
|
||||
{
|
||||
int ret = -1;
|
||||
int quiet = 0;
|
||||
int index = use_index;
|
||||
const char *label_ours = NULL, *label_theirs = NULL, *label_base = NULL;
|
||||
struct stash_info info = STASH_INFO_INIT;
|
||||
struct option options[] = {
|
||||
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
|
||||
OPT_BOOL(0, "index", &index,
|
||||
N_("attempt to recreate the index")),
|
||||
OPT_STRING(0, "label-ours", &label_ours, N_("label"),
|
||||
N_("label for the upstream side in conflict markers")),
|
||||
OPT_STRING(0, "label-theirs", &label_theirs, N_("label"),
|
||||
N_("label for the stashed side in conflict markers")),
|
||||
OPT_STRING(0, "label-base", &label_base, N_("label"),
|
||||
N_("label for the base in diff3 conflict markers")),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
|
@ -754,8 +737,7 @@ static int apply_stash(int argc, const char **argv, const char *prefix,
|
|||
if (get_stash_info(&info, argc, argv))
|
||||
goto cleanup;
|
||||
|
||||
ret = do_apply_stash_with_labels(prefix, &info, index, quiet,
|
||||
label_ours, label_theirs, label_base);
|
||||
ret = do_apply_stash(prefix, &info, index, quiet);
|
||||
cleanup:
|
||||
free_stash_info(&info);
|
||||
return ret;
|
||||
|
|
|
|||
67
sequencer.c
67
sequencer.c
|
|
@ -4657,8 +4657,7 @@ static enum todo_command peek_command(struct todo_list *todo_list, int offset)
|
|||
|
||||
static void create_autostash_internal(struct repository *r,
|
||||
const char *path,
|
||||
const char *refname,
|
||||
bool silent)
|
||||
const char *refname)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct lock_file lock_file = LOCK_INIT;
|
||||
|
|
@ -4703,8 +4702,7 @@ static void create_autostash_internal(struct repository *r,
|
|||
&oid, null_oid(the_hash_algo), 0, UPDATE_REFS_DIE_ON_ERR);
|
||||
}
|
||||
|
||||
if (!silent)
|
||||
printf(_("Created autostash: %s\n"), buf.buf);
|
||||
printf(_("Created autostash: %s\n"), buf.buf);
|
||||
if (reset_head(r, &ropts) < 0)
|
||||
die(_("could not reset --hard"));
|
||||
discard_index(r->index);
|
||||
|
|
@ -4716,22 +4714,15 @@ static void create_autostash_internal(struct repository *r,
|
|||
|
||||
void create_autostash(struct repository *r, const char *path)
|
||||
{
|
||||
create_autostash_internal(r, path, NULL, false);
|
||||
create_autostash_internal(r, path, NULL);
|
||||
}
|
||||
|
||||
void create_autostash_ref(struct repository *r, const char *refname)
|
||||
{
|
||||
create_autostash_internal(r, NULL, refname, false);
|
||||
create_autostash_internal(r, NULL, refname);
|
||||
}
|
||||
|
||||
void create_autostash_ref_silent(struct repository *r, const char *refname)
|
||||
{
|
||||
create_autostash_internal(r, NULL, refname, true);
|
||||
}
|
||||
|
||||
static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply,
|
||||
const char *label_ours, const char *label_theirs,
|
||||
const char *label_base)
|
||||
static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply)
|
||||
{
|
||||
struct child_process child = CHILD_PROCESS_INIT;
|
||||
int ret = 0;
|
||||
|
|
@ -4742,12 +4733,6 @@ static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply,
|
|||
child.no_stderr = 1;
|
||||
strvec_push(&child.args, "stash");
|
||||
strvec_push(&child.args, "apply");
|
||||
if (label_ours)
|
||||
strvec_pushf(&child.args, "--label-ours=%s", label_ours);
|
||||
if (label_theirs)
|
||||
strvec_pushf(&child.args, "--label-theirs=%s", label_theirs);
|
||||
if (label_base)
|
||||
strvec_pushf(&child.args, "--label-base=%s", label_base);
|
||||
strvec_push(&child.args, stash_oid);
|
||||
ret = run_command(&child);
|
||||
}
|
||||
|
|
@ -4766,23 +4751,15 @@ static int apply_save_autostash_oid(const char *stash_oid, int attempt_apply,
|
|||
strvec_push(&store.args, stash_oid);
|
||||
if (run_command(&store))
|
||||
ret = error(_("cannot store %s"), stash_oid);
|
||||
else if (attempt_apply)
|
||||
fprintf(stderr,
|
||||
_("Your local changes are stashed, however, applying it to carry\n"
|
||||
"forward your local changes resulted in conflicts:\n"
|
||||
"\n"
|
||||
" - You can try resolving them now. If you resolved them\n"
|
||||
" successfully, discard the stash entry with \"git stash drop\".\n"
|
||||
"\n"
|
||||
" - Alternatively you can \"git reset --hard\" if you do not want\n"
|
||||
" to deal with them right now, and later \"git stash pop\" to\n"
|
||||
" recover your local changes.\n"));
|
||||
else
|
||||
fprintf(stderr,
|
||||
_("Autostash exists; creating a new stash entry.\n"
|
||||
_("%s\n"
|
||||
"Your changes are safe in the stash.\n"
|
||||
"You can run \"git stash pop\" or"
|
||||
" \"git stash drop\" at any time.\n"));
|
||||
" \"git stash drop\" at any time.\n"),
|
||||
attempt_apply ?
|
||||
_("Applying autostash resulted in conflicts.") :
|
||||
_("Autostash exists; creating a new stash entry."));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -4800,8 +4777,7 @@ static int apply_save_autostash(const char *path, int attempt_apply)
|
|||
}
|
||||
strbuf_trim(&stash_oid);
|
||||
|
||||
ret = apply_save_autostash_oid(stash_oid.buf, attempt_apply,
|
||||
NULL, NULL, NULL);
|
||||
ret = apply_save_autostash_oid(stash_oid.buf, attempt_apply);
|
||||
|
||||
unlink(path);
|
||||
strbuf_release(&stash_oid);
|
||||
|
|
@ -4820,13 +4796,11 @@ int apply_autostash(const char *path)
|
|||
|
||||
int apply_autostash_oid(const char *stash_oid)
|
||||
{
|
||||
return apply_save_autostash_oid(stash_oid, 1, NULL, NULL, NULL);
|
||||
return apply_save_autostash_oid(stash_oid, 1);
|
||||
}
|
||||
|
||||
static int apply_save_autostash_ref(struct repository *r, const char *refname,
|
||||
int attempt_apply,
|
||||
const char *label_ours, const char *label_theirs,
|
||||
const char *label_base)
|
||||
int attempt_apply)
|
||||
{
|
||||
struct object_id stash_oid;
|
||||
char stash_oid_hex[GIT_MAX_HEXSZ + 1];
|
||||
|
|
@ -4842,8 +4816,7 @@ static int apply_save_autostash_ref(struct repository *r, const char *refname,
|
|||
return error(_("autostash reference is a symref"));
|
||||
|
||||
oid_to_hex_r(stash_oid_hex, &stash_oid);
|
||||
ret = apply_save_autostash_oid(stash_oid_hex, attempt_apply,
|
||||
label_ours, label_theirs, label_base);
|
||||
ret = apply_save_autostash_oid(stash_oid_hex, attempt_apply);
|
||||
|
||||
refs_delete_ref(get_main_ref_store(r), "", refname,
|
||||
&stash_oid, REF_NO_DEREF);
|
||||
|
|
@ -4853,20 +4826,12 @@ static int apply_save_autostash_ref(struct repository *r, const char *refname,
|
|||
|
||||
int save_autostash_ref(struct repository *r, const char *refname)
|
||||
{
|
||||
return apply_save_autostash_ref(r, refname, 0, NULL, NULL, NULL);
|
||||
return apply_save_autostash_ref(r, refname, 0);
|
||||
}
|
||||
|
||||
int apply_autostash_ref(struct repository *r, const char *refname)
|
||||
{
|
||||
return apply_save_autostash_ref(r, refname, 1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int apply_autostash_ref_with_labels(struct repository *r, const char *refname,
|
||||
const char *label_ours, const char *label_theirs,
|
||||
const char *label_base)
|
||||
{
|
||||
return apply_save_autostash_ref(r, refname, 1,
|
||||
label_ours, label_theirs, label_base);
|
||||
return apply_save_autostash_ref(r, refname, 1);
|
||||
}
|
||||
|
||||
static int checkout_onto(struct repository *r, struct replay_opts *opts,
|
||||
|
|
|
|||
|
|
@ -230,15 +230,11 @@ void commit_post_rewrite(struct repository *r,
|
|||
|
||||
void create_autostash(struct repository *r, const char *path);
|
||||
void create_autostash_ref(struct repository *r, const char *refname);
|
||||
void create_autostash_ref_silent(struct repository *r, const char *refname);
|
||||
int save_autostash(const char *path);
|
||||
int save_autostash_ref(struct repository *r, const char *refname);
|
||||
int apply_autostash(const char *path);
|
||||
int apply_autostash_oid(const char *stash_oid);
|
||||
int apply_autostash_ref(struct repository *r, const char *refname);
|
||||
int apply_autostash_ref_with_labels(struct repository *r, const char *refname,
|
||||
const char *label_ours, const char *label_theirs,
|
||||
const char *label_base);
|
||||
|
||||
#define SUMMARY_INITIAL_COMMIT (1 << 0)
|
||||
#define SUMMARY_SHOW_AUTHOR_DATE (1 << 1)
|
||||
|
|
|
|||
|
|
@ -61,30 +61,18 @@ create_expected_failure_apply () {
|
|||
First, rewinding head to replay your work on top of it...
|
||||
Applying: second commit
|
||||
Applying: third commit
|
||||
Your local changes are stashed, however, applying it to carry
|
||||
forward your local changes resulted in conflicts:
|
||||
|
||||
- You can try resolving them now. If you resolved them
|
||||
successfully, discard the stash entry with "git stash drop".
|
||||
|
||||
- Alternatively you can "git reset --hard" if you do not want
|
||||
to deal with them right now, and later "git stash pop" to
|
||||
recover your local changes.
|
||||
Applying autostash resulted in conflicts.
|
||||
Your changes are safe in the stash.
|
||||
You can run "git stash pop" or "git stash drop" at any time.
|
||||
EOF
|
||||
}
|
||||
|
||||
create_expected_failure_merge () {
|
||||
cat >expected <<-EOF
|
||||
$(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
|
||||
Your local changes are stashed, however, applying it to carry
|
||||
forward your local changes resulted in conflicts:
|
||||
|
||||
- You can try resolving them now. If you resolved them
|
||||
successfully, discard the stash entry with "git stash drop".
|
||||
|
||||
- Alternatively you can "git reset --hard" if you do not want
|
||||
to deal with them right now, and later "git stash pop" to
|
||||
recover your local changes.
|
||||
Applying autostash resulted in conflicts.
|
||||
Your changes are safe in the stash.
|
||||
You can run "git stash pop" or "git stash drop" at any time.
|
||||
Successfully rebased and updated refs/heads/rebased-feature-branch.
|
||||
EOF
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1666,35 +1666,6 @@ test_expect_success 'restore untracked files even when we hit conflicts' '
|
|||
)
|
||||
'
|
||||
|
||||
test_expect_success 'apply with custom conflict labels' '
|
||||
git init conflict_labels &&
|
||||
(
|
||||
cd conflict_labels &&
|
||||
test_commit base file &&
|
||||
echo stashed >file &&
|
||||
git stash push -m "stashed" &&
|
||||
test_commit upstream file &&
|
||||
test_must_fail git -c merge.conflictStyle=diff3 stash apply --label-ours=UP --label-theirs=STASH &&
|
||||
test_grep "^<<<<<<< UP" file &&
|
||||
test_grep "^||||||| Stash base" file &&
|
||||
test_grep "^>>>>>>> STASH" file
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'apply with empty conflict labels' '
|
||||
git init empty_labels &&
|
||||
(
|
||||
cd empty_labels &&
|
||||
test_commit base file &&
|
||||
echo stashed >file &&
|
||||
git stash push -m "stashed" &&
|
||||
test_commit upstream file &&
|
||||
test_must_fail git stash apply --label-ours= --label-theirs= &&
|
||||
test_grep "^<<<<<<<$" file &&
|
||||
test_grep "^>>>>>>>$" file
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'stash create reports a locked index' '
|
||||
test_when_finished "rm -rf repo" &&
|
||||
git init repo &&
|
||||
|
|
|
|||
195
t/t7201-co.sh
195
t/t7201-co.sh
|
|
@ -210,201 +210,6 @@ test_expect_success 'checkout --merge --conflict=diff3 <branch>' '
|
|||
test_cmp expect two
|
||||
'
|
||||
|
||||
test_expect_success 'checkout --merge --conflict=zdiff3 <branch>' '
|
||||
git checkout -f main &&
|
||||
git reset --hard &&
|
||||
git clean -f &&
|
||||
|
||||
fill a b X d e >two &&
|
||||
git checkout --merge --conflict=zdiff3 simple &&
|
||||
|
||||
cat <<-EOF >expect &&
|
||||
a
|
||||
<<<<<<< simple
|
||||
c
|
||||
||||||| main
|
||||
b
|
||||
c
|
||||
d
|
||||
=======
|
||||
b
|
||||
X
|
||||
d
|
||||
>>>>>>> local
|
||||
e
|
||||
EOF
|
||||
test_cmp expect two
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -m respects merge.conflictStyle config' '
|
||||
git checkout -f main &&
|
||||
git reset --hard &&
|
||||
git clean -f &&
|
||||
|
||||
test_config merge.conflictStyle diff3 &&
|
||||
fill b d >two &&
|
||||
git checkout -m simple &&
|
||||
|
||||
cat <<-EOF >expect &&
|
||||
<<<<<<< simple
|
||||
a
|
||||
c
|
||||
e
|
||||
||||||| main
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
=======
|
||||
b
|
||||
d
|
||||
>>>>>>> local
|
||||
EOF
|
||||
test_cmp expect two
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -m skips stash when no conflict' '
|
||||
git checkout -f main &&
|
||||
git clean -f &&
|
||||
|
||||
fill 0 x y z >same &&
|
||||
git stash list >stash-before &&
|
||||
git checkout -m side >actual 2>&1 &&
|
||||
test_grep ! "Created autostash" actual &&
|
||||
git stash list >stash-after &&
|
||||
test_cmp stash-before stash-after &&
|
||||
fill 0 x y z >expect &&
|
||||
test_cmp expect same
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -m skips stash with non-conflicting dirty index' '
|
||||
git checkout -f main &&
|
||||
git clean -f &&
|
||||
|
||||
fill 0 x y z >same &&
|
||||
git add same &&
|
||||
git checkout -m side >actual 2>&1 &&
|
||||
test_grep ! "Created autostash" actual &&
|
||||
fill 0 x y z >expect &&
|
||||
test_cmp expect same
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -m stashes and applies on conflicting changes' '
|
||||
git checkout -f main &&
|
||||
git clean -f &&
|
||||
|
||||
fill 1 2 3 4 5 6 7 >one &&
|
||||
git checkout -m side >actual 2>&1 &&
|
||||
test_grep ! "Created autostash" actual &&
|
||||
test_grep "Applied autostash" actual &&
|
||||
fill 1 2 3 4 5 6 7 >expect &&
|
||||
test_cmp expect one
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -m with mixed staged and unstaged changes' '
|
||||
git checkout -f main &&
|
||||
git clean -f &&
|
||||
|
||||
fill 0 x y z >same &&
|
||||
git add same &&
|
||||
fill 1 2 3 4 5 6 7 >one &&
|
||||
git checkout -m side >actual 2>&1 &&
|
||||
test_grep ! "Created autostash" actual &&
|
||||
test_grep "Applied autostash" actual &&
|
||||
fill 0 x y z >expect &&
|
||||
test_cmp expect same &&
|
||||
fill 1 2 3 4 5 6 7 >expect &&
|
||||
test_cmp expect one
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -m stashes on truly conflicting changes' '
|
||||
git checkout -f main &&
|
||||
git clean -f &&
|
||||
|
||||
fill 1 2 3 4 5 >one &&
|
||||
test_must_fail git checkout side 2>stderr &&
|
||||
test_grep "Your local changes" stderr &&
|
||||
git checkout -m side >actual 2>&1 &&
|
||||
test_grep ! "Created autostash" actual &&
|
||||
test_grep "resulted in conflicts" actual &&
|
||||
test_grep "git stash drop" actual &&
|
||||
git stash drop &&
|
||||
git reset --hard
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -m produces usable stash on conflict' '
|
||||
git checkout -f main &&
|
||||
git clean -f &&
|
||||
|
||||
fill 1 2 3 4 5 >one &&
|
||||
git checkout -m side >actual 2>&1 &&
|
||||
test_grep "recover your local changes" actual &&
|
||||
git checkout -f main &&
|
||||
git stash pop &&
|
||||
fill 1 2 3 4 5 >expect &&
|
||||
test_cmp expect one
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -m stashes on staged conflicting changes' '
|
||||
git checkout -f main &&
|
||||
git clean -f &&
|
||||
|
||||
fill 1 2 3 4 5 >one &&
|
||||
git add one &&
|
||||
git checkout -m side >actual 2>&1 &&
|
||||
test_grep ! "Created autostash" actual &&
|
||||
test_grep "resulted in conflicts" actual &&
|
||||
test_grep "git stash drop" actual &&
|
||||
git stash drop &&
|
||||
git reset --hard
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -m applies stash cleanly with non-overlapping changes in same file' '
|
||||
git checkout -f main &&
|
||||
git reset --hard &&
|
||||
git clean -f &&
|
||||
|
||||
git checkout -b nonoverlap_base &&
|
||||
fill a b c d >file &&
|
||||
git add file &&
|
||||
git commit -m "add file" &&
|
||||
|
||||
git checkout -b nonoverlap_child &&
|
||||
fill a b c INSERTED d >file &&
|
||||
git commit -a -m "insert line near end of file" &&
|
||||
|
||||
fill DIRTY a b c INSERTED d >file &&
|
||||
|
||||
git stash list >stash-before &&
|
||||
git checkout -m nonoverlap_base 2>stderr &&
|
||||
test_grep "Applied autostash" stderr &&
|
||||
test_grep ! "resulted in conflicts" stderr &&
|
||||
|
||||
git stash list >stash-after &&
|
||||
test_cmp stash-before stash-after &&
|
||||
|
||||
fill DIRTY a b c d >expect &&
|
||||
test_cmp expect file &&
|
||||
|
||||
git checkout -f main &&
|
||||
git branch -D nonoverlap_base &&
|
||||
git branch -D nonoverlap_child
|
||||
'
|
||||
|
||||
test_expect_success 'checkout -m -b skips stash with dirty tree' '
|
||||
git checkout -f main &&
|
||||
git clean -f &&
|
||||
|
||||
fill 0 x y z >same &&
|
||||
git checkout -m -b newbranch >actual 2>&1 &&
|
||||
test_grep ! "Created autostash" actual &&
|
||||
fill 0 x y z >expect &&
|
||||
test_cmp expect same &&
|
||||
git checkout main &&
|
||||
git branch -D newbranch
|
||||
'
|
||||
|
||||
test_expect_success 'switch to another branch while carrying a deletion' '
|
||||
git checkout -f main &&
|
||||
git reset --hard &&
|
||||
|
|
|
|||
|
|
@ -914,7 +914,7 @@ test_expect_success 'merge with conflicted --autostash changes' '
|
|||
git diff >expect &&
|
||||
test_when_finished "test_might_fail git stash drop" &&
|
||||
git merge --autostash c3 2>err &&
|
||||
test_grep "your local changes resulted in conflicts" err &&
|
||||
test_grep "Applying autostash resulted in conflicts." err &&
|
||||
git show HEAD:file >merge-result &&
|
||||
test_cmp result.1-9 merge-result &&
|
||||
git stash show -p >actual &&
|
||||
|
|
|
|||
|
|
@ -325,18 +325,6 @@ int parse_conflict_style_name(const char *value)
|
|||
return -1;
|
||||
}
|
||||
|
||||
const char *conflict_style_name(int style)
|
||||
{
|
||||
switch (style) {
|
||||
case XDL_MERGE_DIFF3:
|
||||
return "diff3";
|
||||
case XDL_MERGE_ZEALOUS_DIFF3:
|
||||
return "zdiff3";
|
||||
default:
|
||||
return "merge";
|
||||
}
|
||||
}
|
||||
|
||||
int git_xmerge_style = -1;
|
||||
|
||||
int git_xmerge_config(const char *var, const char *value,
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags);
|
|||
void xdiff_clear_find_func(xdemitconf_t *xecfg);
|
||||
struct config_context;
|
||||
int parse_conflict_style_name(const char *value);
|
||||
const char *conflict_style_name(int style);
|
||||
int git_xmerge_config(const char *var, const char *value,
|
||||
const struct config_context *ctx, void *cb);
|
||||
extern int git_xmerge_style;
|
||||
|
|
|
|||
|
|
@ -199,9 +199,9 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
|
|||
int size, int i, int style,
|
||||
xdmerge_t *m, char *dest, int marker_size)
|
||||
{
|
||||
int marker1_size = (name1 && *name1 ? strlen(name1) + 1 : 0);
|
||||
int marker2_size = (name2 && *name2 ? strlen(name2) + 1 : 0);
|
||||
int marker3_size = (name3 && *name3 ? strlen(name3) + 1 : 0);
|
||||
int marker1_size = (name1 ? strlen(name1) + 1 : 0);
|
||||
int marker2_size = (name2 ? strlen(name2) + 1 : 0);
|
||||
int marker3_size = (name3 ? strlen(name3) + 1 : 0);
|
||||
int needs_cr = is_cr_needed(xe1, xe2, m);
|
||||
|
||||
if (marker_size <= 0)
|
||||
|
|
|
|||
Loading…
Reference in New Issue