all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Ediff and merge
@ 2009-05-15 19:34 Rasmus Pank Roulund
  0 siblings, 0 replies; 4+ messages in thread
From: Rasmus Pank Roulund @ 2009-05-15 19:34 UTC (permalink / raw)
  To: help-gnu-emacs

Hello,
I have a simple and probably simple question on ediff and merge.
I use SVN. Sometimes conflicts happens. I try to resolve them with
Ediff. I use the 3files mode and use "a" and "b" to select whatever I
want to keep.
However, what to I type to save buffer c and resolve the conflict? It
would be the next logic step but I just cannot find the correct key...
At the moment I do "wc" and save it in place of the conflicted file and
resolve the conflict manually in svn-staus (I use psvn).
I hope somebody can help me out. 
I have read the quick help and a more extended version.

Thanks,
Rasmus 





^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Ediff and merge
       [not found] <mailman.7223.1242416089.31690.help-gnu-emacs@gnu.org>
@ 2009-05-16  4:30 ` Giorgos Keramidas
  2009-05-16 10:28   ` Rasmus Pank Roulund
       [not found]   ` <mailman.7259.1242469777.31690.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 4+ messages in thread
From: Giorgos Keramidas @ 2009-05-16  4:30 UTC (permalink / raw)
  To: help-gnu-emacs

On Fri, 15 May 2009 21:34:23 +0200, Rasmus Pank Roulund <rasmus.pank@gmail.com> wrote:
> Hello,
>
> I have a simple and probably simple question on ediff and merge.  I
> use SVN. Sometimes conflicts happens. I try to resolve them with
> Ediff. I use the 3files mode and use "a" and "b" to select whatever I
> want to keep.

ediff is a fine tool for merging conflicts in 3-way mode.  I use it all
the time for subversion, mercurial and perforce merges, and it has
slowly become one of the tools I consider indispensable when working
with version-controlled files.

The recent releases of Subversion support a config option to integrate
your own 3-way merge tool with the `svn merge' command.  That's what I
use locally to integrate ediff with subversion merging.

You first have to set the following option in the `config' file of your
`~/.subversion' directory.  Open the file and look for the section
called [helpers].  You can add the `merge-tool-cmd' option at that
section:

    [helpers]
    merge-tool-cmd = svn-ediff-merge

Then save the following script as `svn-ediff-merge', make it executable
and save it somewhere in your PATH so svn(1) can find it:

,-----------------------------------------------------------------------
| #!/bin/sh
| #
| # svn-merge -- merge wrapper around ediff-mode for Subversion
| #
| # Copyright (c) 2006-2009 Giorgos Keramidas <keramida@FreeBSD.org>
| # All rights reserved.
| #
| # Redistribution and use in source and binary forms, with or without
| # modification, are permitted provided that the following conditions
| # are met:
| # 1. Redistributions of source code must retain the above copyright
| #    notice, this list of conditions and the following disclaimer.
| # 2. Redistributions in binary form must reproduce the above copyright
| #    notice, this list of conditions and the following disclaimer in the
| #    documentation and/or other materials provided with the distribution.
| #
| # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
| # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
| # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
| # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
| # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
| # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
| # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
| # SUCH DAMAGE.
|
| if test $# -ne 4 ; then
|         echo >&2 "usage: `basename $0` BASE OTHER LOCAL MERGED"
|         exit 1
| fi
|
| #
| # Subversion calls the program specified as `merge-tool-cmd' with four
| # filename arguments:
| #
| #   BASE  = base revision; the common ancestor of $other and $local
| #   OTHER = parent branch version
| #   LOCAL = locally modified version
| #   WC    = working copy; the file where merge results should be saved
| #
| # We have to take care to save these filename arguments, and then run
| # ediff-mode with the right options.  When the merge is finished, the
| # working copy of the file at ${WC} should contain the merge results.
| #
|
| BASE="$1"
| OTHER="$2"
| LOCAL="$3"
| WC="$4"
|
| cleanup() {
|         # We failed.  If ${RESTORE} is set, then we are supposed to have
|         # the pathname of a ${BACKUP} copy, and we should restore ${BACKUP}
|         # to ${LOCAL} and ${LOCAL} to ${WC} before dying.
|
|         CLEANUP=true            # Make sure we don't recurse forever.
|
|         test -z "${RESTORE}"            && return
|         test X"${RESTORE}" = X'yes'     || return
|
|         if test -z "${BACKUP}" || test -z "${LOCAL}" ; then
|                 err 1 "internal merge script error."
|         fi
|
|         cat "${BACKUP}" > "${LOCAL}" && rm "${BACKUP}"
|         if test $? -ne 0 ; then
|                 err 1 "Cannot restore ${LOCAL} -- workspace may be *unclean*"
|         fi
|
|         return 0
| }
|
| success() {
|         if test -z "${BACKUP}" || test -z "${LOCAL}" ; then
|                 err 1 "internal merge script error."
|         fi
|
|         # The merge was successful.  Remove the backup copy of ${LOCAL}.
|         if test -n "${BACKUP}" ; then
|                 /bin/rm -f "${BACKUP}"
|         fi
|
|         # When the merge is successful, ediff has left the merge results
|         # into $LOCAL.  Copy them over $WC to let `svn merge' know that
|         # we are done.
|         cat "${LOCAL}" > "${WC}"
|         if test $? -ne 0 ; then
|                 err 1 "Cannot restore ${WC} -- workspace is *unclean*"
|         fi
| }
|
| err() {
|         errcode=$1
|         shift
|         echo >&2 "`basename $0`: error: $*"
|         if test -z "${CLEANUP}" ; then
|                 cleanup
|         fi
|         exit $errcode
| }
|
| # Set $EMACS_PROGRAM in the environment of the merge script to the name of
| # the Emacs binary you want to use.  If unset, it defaults to `emacs' and it
| # also affects the default $EDITOR below.
| EMACS_PROGRAM="${EMACS_PROGRAM:-emacs}"
| export EMACS_PROGRAM
|
| # Since this script depends on manual edits being performed to the files being
| # merged, make sure that ${EDITOR} is truly set to something, even if this is
| # just plain good ol' vi(1).
| EDITOR="${EDITOR:-${EMACS_PROGRAM}}"
| export EDITOR
|
| # First make sure $TMPDIR points to a meaningful directory.  We will be using
| # this shell variable further down, so it's a good idea to make sure it isn't
| # empty later on.
| TMPDIR="${TMPDIR:-/var/tmp}"
| export TMPDIR
|
| # We depend on diff3(1) being available to do the first pass of the merge,
| # adding conflict markers around the areas that should be edited.
| which diff3 >/dev/null 2>&1
| if test $? -ne 0 ; then
|         err 1 "No diff3(1) utility found in the current PATH."
| fi
|
| # We will be using a temporary file with the diff3(1) output as the merge
| # buffer, until either the merge removes all conflict markers from the working
| # copy of the file or we fail somehow to complete the merge.
| BACKUP=`mktemp "${TMPDIR}/svnmerge.$$.XXXXXX"`
| if test $? -ne 0 ; then
|         err 1 "Cannot create backup file at ${TMPDIR}/hgmerge.$$.XXXXXX"
| fi
|
| # Save a backup copy of the $LOCAL file version.
| cp "${LOCAL}" "${BACKUP}" && RESTORE='yes'
| rc=$?
| if test $rc -ne 0 ; then
|         err 1 "Cannot create backup file at ${BACKUP}"
| fi
|
| # If the remote and the local file have no differences, then there's
| # nothing to merge.  Accept both :)
| if cmp "${LOCAL}" "${OTHER}" > /dev/null 2>&1 ; then
|         success
|         exit 0
| fi
|
| LABEL=`basename "${LOCAL}"`
| diff3 -m \
|     -L "${LABEL}" -L "${LABEL}.base" -L "${LABEL}.other" \
|     "${BACKUP}" "${BASE}" "${OTHER}" > "${LOCAL}"
| rc=$?
| if test $rc -eq 0 ; then
|         # No conflicts found.  Merge done.
|         success
|         exit 0
| elif test $rc -gt 1 ; then
|         err 1 "serious diff3 error, while trying to merge ${LOCAL}"
| fi
|
| # In all other cases, diff3(1) has found conflicts, added the proper
| # conflict markers to the ${LOCAL} file.  Revert from the ${BACKUP}
| # copy of the file, and spawn an emacs+ediff merge session.
| #
| # Editing the ${LOCAL} file "pollutes" the workspace area, but the filename
| # shown in the editor buffer _really_ reflects the workspace path of the
| # ${LOCAL} file, which is very helpful with editors (i.e. it lets the
| # editor autopick the right 'mode' for editing the file, and so on).
| cat "${BACKUP}" > "${LOCAL}" && \
| ${EMACS_PROGRAM} --eval "(ediff-merge-with-ancestor \"$BACKUP\" \"$OTHER\" \"$BASE\" nil \"$LOCAL\")"
| if test $? -ne 0 ; then
|         err 1 "merge error for ${LOCAL}"
| fi
|
| # When the editor exits, there should be no conflict markers in the
| # ${LOCAL} copy of the filefile, otherwise we consider the merge failed.
| if grep '^>>>> ORIGINAL' "${LOCAL}" >/dev/null 2>&1 ; then
|         err 1 "'^>>>> ORIGINAL' conflict markers" \
|             "still found in the working-copy." \
|             "Merge aborted for ${LOCAL}"
| fi
| if grep '^==== THEIRS' "${LOCAL}" >/dev/null 2>&1 ; then
|         err 1 "'^==== THEIRS' conflict markers" \
|             "still found in the working-copy." \
|             "Merge aborted for ${LOCAL}"
| fi
| if grep '^==== YOURS' "${LOCAL}" >/dev/null 2>&1 ; then
|         err 1 "'^==== YOURS' conflict markers" \
|             "still found in the working-copy." \
|             "Merge aborted for ${LOCAL}"
| fi
| if grep '^<<<<' "${LOCAL}" >/dev/null 2>&1 ; then
|         err 1 "'^<<<<' conflict markers" \
|             "still found in the working-copy." \
|             "Merge aborted for ${LOCAL}"
| fi
|
| success                         # The merge has completed successfully.
| exit 0
`-----------------------------------------------------------------------

Now whenever `svn merge' prompts you for a conflict, you should be able
to type `l' (the shortcut for `launch external merge tool') to fire up
an Emacs instance in ediff's 3-way merge mode.

When you save the merged buffer, the script will take care of saving the
merged file in your workspace.  Then you can type `r' (resolved) at the
svn merge prompt, and you are done.



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Ediff and merge
  2009-05-16  4:30 ` Giorgos Keramidas
@ 2009-05-16 10:28   ` Rasmus Pank Roulund
       [not found]   ` <mailman.7259.1242469777.31690.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 4+ messages in thread
From: Rasmus Pank Roulund @ 2009-05-16 10:28 UTC (permalink / raw)
  To: help-gnu-emacs

Hello Giorgos,

Yeah ediff is great. I use svn from within emacs with psvn.el. The tool
is called svn-status within emacs. It has built in support for Ediff. I
just RET on a conflicted file and it go to SMerge minor mode (I think)
and from there I can enter ediff.

However, I think "R" is the command I am looking for. When I "A" and
"B"'ed through all the conflict points and I am done I need the command
to end it naturally.

The script you posted looks interesting. Would you be able to post it
again as an attached file? The line breaking has been broken in my
Gnus. Is this script mainly for command line or will it have an effect
when I use SVN through an emacs-mode like psvn.el?


> When you save the merged buffer, the script will take care of saving
> the merged file in your workspace.  Then you can type `r' (resolved)
> at the svn merge prompt, and you are done.
This is really the funcitonallity I am looking for! Is it built into
ediff or do I need your script to perform this action?

Thank you so much for your help!
Rasmus






^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Ediff and merge
       [not found]   ` <mailman.7259.1242469777.31690.help-gnu-emacs@gnu.org>
@ 2009-05-17  4:30     ` Giorgos Keramidas
  0 siblings, 0 replies; 4+ messages in thread
From: Giorgos Keramidas @ 2009-05-17  4:30 UTC (permalink / raw)
  To: help-gnu-emacs

On Sat, 16 May 2009 12:28:23 +0200, Rasmus Pank Roulund <rasmus.pank@gmail.com> wrote:
> Hello Giorgos,
> Yeah ediff is great. I use svn from within emacs with psvn.el. The
> tool is called svn-status within emacs. It has built in support for
> Ediff. I just RET on a conflicted file and it go to SMerge minor mode
> (I think) and from there I can enter ediff.
>
> However, I think "R" is the command I am looking for. When I "A" and
> "B"'ed through all the conflict points and I am done I need the
> command to end it naturally.

Ah, I see.  I haven't used psvn (the VC support for svn is mostly fine
for what I usually do), so I am not sure if the script I posted can fit
well with psvn.

> The script you posted looks interesting. Would you be able to post it
> again as an attached file? The line breaking has been broken in my
> Gnus. Is this script mainly for command line or will it have an effect
> when I use SVN through an emacs-mode like psvn.el?

Sure, I can attach it, but I am reading gnu.emacs.help posts through
NNTP, so it may not come through.  I uploaded a copy to:

  http://people.freebsd.org/~keramida/svn-ediff-merge.sh

I have only used the script with the command-line merges of "svn
merge".  It may be easy to hack the script a bit and integrate it with
psvn, but I am not sure if that would work or if it would useful.

> This is really the funcitonallity I am looking for! Is it built into
> ediff or do I need your script to perform this action?

It is part of the interaction between the command-line svn(1) utility
and the way the script works.  svn(1) passes filename paths to the
script.  These filename arguments are described in the toplevel comments
of the script:

#   BASE  = base revision; the common ancestor of $other and $local
#   OTHER = parent branch version
#   LOCAL = locally modified version
#   WC    = working copy; the file where merge results should be saved

The `WC' filename (positional argument $4) is the path of the file
inside the subversion workspace, so the script tries to save any
successful merge result to that path.



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-05-17  4:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-15 19:34 Ediff and merge Rasmus Pank Roulund
     [not found] <mailman.7223.1242416089.31690.help-gnu-emacs@gnu.org>
2009-05-16  4:30 ` Giorgos Keramidas
2009-05-16 10:28   ` Rasmus Pank Roulund
     [not found]   ` <mailman.7259.1242469777.31690.help-gnu-emacs@gnu.org>
2009-05-17  4:30     ` Giorgos Keramidas

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.