Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new goal, "manual". #38

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ history.
discard the
intermediate merge commits and create a simpler history to record
permanently in your project repository using either the ``finish`` or
``simplify`` command. The "goal" of the incremental merge can be one
of the following:
``simplify`` command. The incremental merge can be simplified in one
of four ways:

``merge``
keep only a simple merge of the second branch into the first
Expand All @@ -100,6 +100,13 @@ of the following:
git checkout BRANCH1
git merge BRANCH2

``manual``
like ``merge``, but also keep any merges that had to be done
manually plus enough automatic merges to connect the manual merges
together meaningfully. If the result is later discovered to be
buggy, the additional information might be helpful in isolating
the problem.

``rebase``
keep the versions of the commits from the second branch rebased
onto the first branch. The end result is similar to what you
Expand Down
3 changes: 0 additions & 3 deletions TODO.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ Convenience features
New merge goals and styles
==========================

* Add a ``--goal=sparse`` option that retains all of the conflicted
merges and enough intermediate history to connect them.

* Add an option that allows the user to resolve conflicts in larger
chunks; for example, add a rebase-with-history-type merge where each
branch commit is merged directly to its final location on the last
Expand Down
69 changes: 69 additions & 0 deletions git-imerge
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ where
git checkout BRANCH1
git merge BRANCH2

* manual
like merge, but also keep any merges that had to be done
manually plus enough automatic merges to connect the
manual merges together meaningfully. If the merge is
later discovered to be buggy, the additional information
might be helpful in isolating the problem.

* rebase
keep the versions of the commits from the second branch
rebased onto the first branch. The end result is similar
Expand Down Expand Up @@ -198,6 +205,7 @@ ZEROS = '0' * 40

ALLOWED_GOALS = [
'full',
'manual',
'rebase-with-history',
'rebase',
'merge',
Expand Down Expand Up @@ -2308,6 +2316,65 @@ class MergeState(Block):

self._set_refname(refname, self[-1, -1].sha1, force=force)

def simplify_to_manual(self, refname, force=False):
i1s = set()
i2s = set()
for i2 in range(1, self.len2):
for i1 in range(1, self.len1):
record = self[i1,i2]
if record.is_known() and record.is_manual():
i1s.add(i1)
i2s.add(i2)
if not i1s:
# No manual merges were needed; simplify to merge instead.
self.simplify_to_merge(refname, force=force)
return

i1s = sorted(i1s.union([0, self.len1 - 1]))
i2s = sorted(i2s.union([0, self.len2 - 1]))

for i2 in i2s:
for i1 in i1s:
if not (i1, i2) in self:
raise Failure(
'Cannot simplify to "manual" because '
'merge %d-%d is not yet done'
% (i1, i2)
)

# A map {(i1, i2) : sha1} for the grid commits that will be
# retained:
keepers = {}
keepers.update(((i1,0), self[i1,0].sha1) for i1 in i1s)
keepers.update(((0,i2), self[0,i2].sha1) for i2 in i2s)

for index1 in range(1, len(i1s)):
i1 = i1s[index1]
for index2 in range(1, len(i2s)):
i2 = i2s[index2]
tree = get_tree(self[i1, i2].sha1)
parents = [
keepers[i1, i2s[index2 - 1]],
keepers[i1s[index1 - 1], i2],
]

if index1 == len(i1s) - 1 and index2 == len(i2s) - 1:
# Handle the last commit specially. First create
# a preliminary commit with a generic commit
# message:
sha1 = commit_tree(
tree, parents,
msg='Merge %s into %s (using imerge)' % (self.tip2, self.tip1),
)

self._set_refname(refname, sha1, force=force)

# Now let the user edit the commit log message:
check_call(['git', 'commit', '--amend'])
else:
msg = get_log_message(self[i1, i2].sha1)
keepers[i1, i2] = commit_tree(tree, parents, msg=msg)

def simplify_to_rebase_with_history(self, refname, force=False):
i1 = self.len1 - 1
for i2 in range(1, self.len2):
Expand Down Expand Up @@ -2400,6 +2467,8 @@ class MergeState(Block):

if self.goal == 'full':
self.simplify_to_full(refname, force=force)
elif self.goal == 'manual':
self.simplify_to_manual(refname, force=force)
elif self.goal == 'rebase-with-history':
self.simplify_to_rebase_with_history(refname, force=force)
elif self.goal == 'rebase':
Expand Down
3 changes: 2 additions & 1 deletion t/test-conflicted
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cd "$TMP"
# Clean up detritus from possible previous runs of this test:
git checkout master
"$GIT_IMERGE" remove --name=c-d || true
for b in c-d-merge c-d-rebase c-d-rebase-with-history c-d-full
for b in c-d-merge c-d-manual c-d-rebase c-d-rebase-with-history c-d-full
do
git branch -D $b || true
done
Expand All @@ -33,6 +33,7 @@ git add conflict.txt
GIT_EDITOR=cat "$GIT_IMERGE" simplify --goal=merge --branch=c-d-merge
"$GIT_IMERGE" simplify --goal=rebase --branch=c-d-rebase
"$GIT_IMERGE" simplify --goal=rebase-with-history --branch=c-d-rebase-with-history
GIT_EDITOR=cat "$GIT_IMERGE" simplify --goal=manual --branch=c-d-manual
"$GIT_IMERGE" remove

git checkout c
Expand Down
5 changes: 3 additions & 2 deletions t/test-unconflicted
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cd "$TMP"
# Clean up detritus from possible previous runs:
git checkout master
"$GIT_IMERGE" remove --name=a-b || true
for b in a-b-merge a-b-rebase a-b-rebase-with-history a-b-full
for b in a-b-merge a-b-manual a-b-rebase a-b-rebase-with-history a-b-full
do
git branch -D $b || true
done
Expand All @@ -32,5 +32,6 @@ git checkout a
"$GIT_IMERGE" start --goal=full --first-parent --name=a-b b
"$GIT_IMERGE" list
"$GIT_IMERGE" diagram --commits --frontier --html=imerge4.html
"$GIT_IMERGE" finish --branch=a-b-full
"$GIT_IMERGE" simplify --branch=a-b-full
GIT_EDITOR=cat "$GIT_IMERGE" finish --goal=manual --branch=a-b-manual