Skip to content

Commit

Permalink
Merge branch 'jh/notes-merge'
Browse files Browse the repository at this point in the history
* jh/notes-merge: (23 commits)
  Provide 'git merge --abort' as a synonym to 'git reset --merge'
  cmd_merge(): Parse options before checking MERGE_HEAD
  Provide 'git notes get-ref' to easily retrieve current notes ref
  git notes merge: Add testcases for merging notes trees at different fanouts
  git notes merge: Add another auto-resolving strategy: "cat_sort_uniq"
  git notes merge: --commit should fail if underlying notes ref has moved
  git notes merge: List conflicting notes in notes merge commit message
  git notes merge: Manual conflict resolution, part 2/2
  git notes merge: Manual conflict resolution, part 1/2
  Documentation: Preliminary docs on 'git notes merge'
  git notes merge: Add automatic conflict resolvers (ours, theirs, union)
  git notes merge: Handle real, non-conflicting notes merges
  builtin/notes.c: Refactor creation of notes commits.
  git notes merge: Initial implementation handling trivial merges only
  builtin/notes.c: Split notes ref DWIMmery into a separate function
  notes.c: Use two newlines (instead of one) when concatenating notes
  (trivial) t3303: Indent with tabs instead of spaces for consistency
  notes.h/c: Propagate combine_notes_fn return value to add_note() and beyond
  notes.h/c: Allow combine_notes functions to remove notes
  notes.c: Reorder functions in preparation for next commit
  ...

Conflicts:
	builtin.h
  • Loading branch information
gitster committed Dec 8, 2010
2 parents f04aa35 + 35d2fff commit 657072f
Show file tree
Hide file tree
Showing 20 changed files with 3,794 additions and 162 deletions.
27 changes: 24 additions & 3 deletions Documentation/git-merge.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ SYNOPSIS
[-s <strategy>] [-X <strategy-option>]
[--[no-]rerere-autoupdate] [-m <msg>] <commit>...
'git merge' <msg> HEAD <commit>...
'git merge' --abort

DESCRIPTION
-----------
Expand Down Expand Up @@ -47,6 +48,14 @@ The second syntax (<msg> `HEAD` <commit>...) is supported for
historical reasons. Do not use it from the command line or in
new scripts. It is the same as `git merge -m <msg> <commit>...`.

The third syntax ("`git merge --abort`") can only be run after the
merge has resulted in conflicts. 'git merge --abort' will abort the
merge process and try to reconstruct the pre-merge state. However,
if there were uncommitted changes when the merge started (and
especially if those changes were further modified after the merge
was started), 'git merge --abort' will in some cases be unable to
reconstruct the original (pre-merge) changes. Therefore:

*Warning*: Running 'git merge' with uncommitted changes is
discouraged: while possible, it leaves you in a state that is hard to
back out of in the case of a conflict.
Expand All @@ -72,6 +81,18 @@ invocations.
Allow the rerere mechanism to update the index with the
result of auto-conflict resolution if possible.

--abort::
Abort the current conflict resolution process, and
try to reconstruct the pre-merge state.
+
If there were uncommitted worktree changes present when the merge
started, 'git merge --abort' will in some cases be unable to
reconstruct these changes. It is therefore recommended to always
commit or stash your changes before running 'git merge'.
+
'git merge --abort' is equivalent to 'git reset --merge' when
`MERGE_HEAD` is present.

<commit>...::
Commits, usually other branch heads, to merge into our branch.
You need at least one <commit>. Specifying more than one
Expand Down Expand Up @@ -142,7 +163,7 @@ happens:
i.e. matching `HEAD`.

If you tried a merge which resulted in complex conflicts and
want to start over, you can recover with `git reset --merge`.
want to start over, you can recover with `git merge --abort`.

HOW CONFLICTS ARE PRESENTED
---------------------------
Expand Down Expand Up @@ -213,8 +234,8 @@ After seeing a conflict, you can do two things:

* Decide not to merge. The only clean-ups you need are to reset
the index file to the `HEAD` commit to reverse 2. and to clean
up working tree changes made by 2. and 3.; `git-reset --hard` can
be used for this.
up working tree changes made by 2. and 3.; `git merge --abort`
can be used for this.

* Resolve the conflicts. Git will mark the conflicts in
the working tree. Edit the files into shape and
Expand Down
85 changes: 84 additions & 1 deletion Documentation/git-notes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ SYNOPSIS
'git notes' append [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]
'git notes' edit [<object>]
'git notes' show [<object>]
'git notes' merge [-v | -q] [-s <strategy> ] <notes_ref>
'git notes' merge --commit [-v | -q]
'git notes' merge --abort [-v | -q]
'git notes' remove [<object>]
'git notes' prune [-n | -v]
'git notes' get-ref


DESCRIPTION
Expand Down Expand Up @@ -83,6 +87,21 @@ edit::
show::
Show the notes for a given object (defaults to HEAD).

merge::
Merge the given notes ref into the current notes ref.
This will try to merge the changes made by the given
notes ref (called "remote") since the merge-base (if
any) into the current notes ref (called "local").
+
If conflicts arise and a strategy for automatically resolving
conflicting notes (see the -s/--strategy option) is not given,
the "manual" resolver is used. This resolver checks out the
conflicting notes in a special worktree (`.git/NOTES_MERGE_WORKTREE`),
and instructs the user to manually resolve the conflicts there.
When done, the user can either finalize the merge with
'git notes merge --commit', or abort the merge with
'git notes merge --abort'.

remove::
Remove the notes for a given object (defaults to HEAD).
This is equivalent to specifying an empty note message to
Expand All @@ -91,6 +110,10 @@ remove::
prune::
Remove all notes for non-existing/unreachable objects.

get-ref::
Print the current notes ref. This provides an easy way to
retrieve the current notes ref (e.g. from scripts).

OPTIONS
-------
-f::
Expand Down Expand Up @@ -133,9 +156,37 @@ OPTIONS
Do not remove anything; just report the object names whose notes
would be removed.

-s <strategy>::
--strategy=<strategy>::
When merging notes, resolve notes conflicts using the given
strategy. The following strategies are recognized: "manual"
(default), "ours", "theirs", "union" and "cat_sort_uniq".
See the "NOTES MERGE STRATEGIES" section below for more
information on each notes merge strategy.

--commit::
Finalize an in-progress 'git notes merge'. Use this option
when you have resolved the conflicts that 'git notes merge'
stored in .git/NOTES_MERGE_WORKTREE. This amends the partial
merge commit created by 'git notes merge' (stored in
.git/NOTES_MERGE_PARTIAL) by adding the notes in
.git/NOTES_MERGE_WORKTREE. The notes ref stored in the
.git/NOTES_MERGE_REF symref is updated to the resulting commit.

--abort::
Abort/reset a in-progress 'git notes merge', i.e. a notes merge
with conflicts. This simply removes all files related to the
notes merge.

-q::
--quiet::
When merging notes, operate quietly.

-v::
--verbose::
Report all object names whose notes are removed.
When merging notes, be more verbose.
When pruning notes, report all object names whose notes are
removed.


DISCUSSION
Expand Down Expand Up @@ -163,6 +214,38 @@ object, in which case the history of the notes can be read with
`git log -p -g <refname>`.


NOTES MERGE STRATEGIES
----------------------

The default notes merge strategy is "manual", which checks out
conflicting notes in a special work tree for resolving notes conflicts
(`.git/NOTES_MERGE_WORKTREE`), and instructs the user to resolve the
conflicts in that work tree.
When done, the user can either finalize the merge with
'git notes merge --commit', or abort the merge with
'git notes merge --abort'.

"ours" automatically resolves conflicting notes in favor of the local
version (i.e. the current notes ref).

"theirs" automatically resolves notes conflicts in favor of the remote
version (i.e. the given notes ref being merged into the current notes
ref).

"union" automatically resolves notes conflicts by concatenating the
local and remote versions.

"cat_sort_uniq" is similar to "union", but in addition to concatenating
the local and remote versions, this strategy also sorts the resulting
lines, and removes duplicate lines from the result. This is equivalent
to applying the "cat | sort | uniq" shell pipeline to the local and
remote versions. This strategy is useful if the notes follow a line-based
format where one wants to avoid duplicated lines in the merge result.
Note that if either the local or remote version contain duplicate lines
prior to the merge, these will also be removed by this notes merge
strategy.


EXAMPLES
--------

Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ LIB_H += mailmap.h
LIB_H += merge-recursive.h
LIB_H += notes.h
LIB_H += notes-cache.h
LIB_H += notes-merge.h
LIB_H += object.h
LIB_H += pack.h
LIB_H += pack-refs.h
Expand Down Expand Up @@ -615,6 +616,7 @@ LIB_OBJS += merge-recursive.o
LIB_OBJS += name-hash.o
LIB_OBJS += notes.o
LIB_OBJS += notes-cache.o
LIB_OBJS += notes-merge.o
LIB_OBJS += object.o
LIB_OBJS += pack-check.o
LIB_OBJS += pack-refs.o
Expand Down
2 changes: 1 addition & 1 deletion builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ extern const char git_more_info_string[];
extern void prune_packed_objects(int);
extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
int merge_title, int shortlog_len);
extern int commit_notes(struct notes_tree *t, const char *msg);
extern void commit_notes(struct notes_tree *t, const char *msg);

struct notes_rewrite_cfg {
struct notes_tree **trees;
Expand Down
47 changes: 31 additions & 16 deletions builtin/merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ static const char *branch;
static int option_renormalize;
static int verbosity;
static int allow_rerere_auto;
static int abort_current_merge;

static struct strategy all_strategy[] = {
{ "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL },
Expand Down Expand Up @@ -197,6 +198,8 @@ static struct option builtin_merge_options[] = {
"message to be used for the merge commit (if any)",
option_parse_message),
OPT__VERBOSITY(&verbosity),
OPT_BOOLEAN(0, "abort", &abort_current_merge,
"abort the current in-progress merge"),
OPT_END()
};

Expand Down Expand Up @@ -919,22 +922,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
const char *best_strategy = NULL, *wt_strategy = NULL;
struct commit_list **remotes = &remoteheads;

if (read_cache_unmerged()) {
die_resolve_conflict("merge");
}
if (file_exists(git_path("MERGE_HEAD"))) {
/*
* There is no unmerged entry, don't advise 'git
* add/rm <file>', just 'git commit'.
*/
if (advice_resolve_conflict)
die("You have not concluded your merge (MERGE_HEAD exists).\n"
"Please, commit your changes before you can merge.");
else
die("You have not concluded your merge (MERGE_HEAD exists).");
}

resolve_undo_clear();
/*
* Check if we are _not_ on a detached HEAD, i.e. if there is a
* current branch.
Expand All @@ -953,6 +940,34 @@ int cmd_merge(int argc, const char **argv, const char *prefix)

argc = parse_options(argc, argv, prefix, builtin_merge_options,
builtin_merge_usage, 0);

if (abort_current_merge) {
int nargc = 2;
const char *nargv[] = {"reset", "--merge", NULL};

if (!file_exists(git_path("MERGE_HEAD")))
die("There is no merge to abort (MERGE_HEAD missing).");

/* Invoke 'git reset --merge' */
return cmd_reset(nargc, nargv, prefix);
}

if (read_cache_unmerged())
die_resolve_conflict("merge");

if (file_exists(git_path("MERGE_HEAD"))) {
/*
* There is no unmerged entry, don't advise 'git
* add/rm <file>', just 'git commit'.
*/
if (advice_resolve_conflict)
die("You have not concluded your merge (MERGE_HEAD exists).\n"
"Please, commit your changes before you can merge.");
else
die("You have not concluded your merge (MERGE_HEAD exists).");
}
resolve_undo_clear();

if (verbosity < 0)
show_diffstat = 0;

Expand Down
Loading

0 comments on commit 657072f

Please sign in to comment.