git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Add function to checkout a branch in git.el
@ 2008-02-13 15:53 =?utf-8?q?R=C3=A9mi=20Vanicat?=
  2008-02-13 16:30 ` Karl Hasselström
  2008-02-13 18:29 ` [PATCH] Add function to checkout a branch " Sergei Organov
  0 siblings, 2 replies; 14+ messages in thread
From: =?utf-8?q?R=C3=A9mi=20Vanicat?= @ 2008-02-13 15:53 UTC (permalink / raw)
  To: git; +Cc: Alexandre Julliard

One can now:
- checkout an existing branch with M-x git-change-branch
- create and checkout a new branch with C-u M-x git-change-branch
- do all this from the Git menu
---
It could also be interesting to add some  key biding for those

Also one might want to update the *git-status* buffer after checkout,
but this is not done by this patch
 contrib/emacs/git.el |   45 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index a8bf0ef..404c8e6 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1138,6 +1138,50 @@ Return the list of files that haven't been handled."
   (when (eq (window-buffer) (current-buffer))
     (shrink-window-if-larger-than-buffer)))
 
+(defun git-list-branch ()
+  "Return a list of available branch"
+  ;; should I check if I'm in a git repository ?
+  (let ((branchs ()))
+    (with-temp-buffer
+      (git-run-command-buffer (current-buffer) "branch")
+      (goto-char (point-min))
+      (while (re-search-forward "^\\([ *]\\) \\([^\n]*\\)$" () t)
+	(push (list (match-string 2)
+		    (string= (match-string 1) "*"))
+	      branchs)))
+    (nreverse branchs)))
+
+(defun git-change-branch (branch &optional new)
+  "Switch to another branch
+
+With a prefix argument, switch to a new branch, ortherwise use
+an existing one"
+  (interactive
+   (if current-prefix-arg
+       (list (read-from-minibuffer "Branch: ")
+	     current-prefix-arg)
+       (list (completing-read "Branch: " (git-list-branch) () t)
+	     current-prefix-arg)))
+  (with-temp-buffer
+    (if new
+	(git-call-process-display-error "checkout" "-b" branch)
+	(git-call-process-display-error "checkout" branch))
+    (goto-char (point-min))))
+
+(defun git-change-new-branch-menu (branch)
+  "Switch to new branch"
+  (interactive "MBranch: ")
+  (git-change-branch branch 't))
+
+(defun git-change-branch-menu-filter (rest)
+  "define the change branch menu"
+  (append
+   (mapcar
+    (lambda (branch)
+      `[,(car branch) (git-change-branch ,(car branch)) t])
+    (git-list-branch))
+   (list ["change to new" git-change-new-branch-menu t])))
+
 (defun git-diff-file ()
   "Diff the marked file(s) against HEAD."
   (interactive)
@@ -1486,6 +1530,7 @@ amended version of it."
 	["Diff Against Merge Head" git-diff-file-merge-head t]
 	["Diff Against Mine" git-diff-file-mine t]
 	["Diff Against Other" git-diff-file-other t])
+      ("Change branch" :filter git-change-branch-menu-filter)
       "--------"
       ["Add File" git-add-file t]
       ["Revert File" git-revert-file t]
-- 
1.5.4.1.101.gacba

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

* Re: [PATCH] Add function to checkout a branch in git.el
  2008-02-13 15:53 [PATCH] Add function to checkout a branch in git.el =?utf-8?q?R=C3=A9mi=20Vanicat?=
@ 2008-02-13 16:30 ` Karl Hasselström
  2008-02-13 16:43   ` Karl Hasselström
  2008-02-13 18:29 ` [PATCH] Add function to checkout a branch " Sergei Organov
  1 sibling, 1 reply; 14+ messages in thread
From: Karl Hasselström @ 2008-02-13 16:30 UTC (permalink / raw)
  To: =?utf-8?q?R=C3=A9mi=20Vanicat?=; +Cc: git, Alexandre Julliard

On 2008-02-13 16:53:12 +0100, =?utf-8?q?R=C3=A9mi=20Vanicat?= wrote:

> - checkout an existing branch with M-x git-change-branch
> - create and checkout a new branch with C-u M-x git-change-branch

Why the prefix? Wouldn't it be easier to just have one "switch branch"
prompt that would tab complete existing branch names, and

  * if the user enters the name of an existing branch, just switch to
    it;

  * if the user enters a name that's not the name of an existing
    branch, ask for confirmation, and then create the new branch and
    switch to it.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

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

* Re: [PATCH] Add function to checkout a branch in git.el
  2008-02-13 16:30 ` Karl Hasselström
@ 2008-02-13 16:43   ` Karl Hasselström
  2008-02-13 18:09     ` Remi Vanicat
  2008-02-13 18:23     ` Sergei Organov
  0 siblings, 2 replies; 14+ messages in thread
From: Karl Hasselström @ 2008-02-13 16:43 UTC (permalink / raw)
  To: =?utf-8?q?R=C3=A9mi=20Vanicat?=; +Cc: git, Alexandre Julliard

On 2008-02-13 17:30:02 +0100, Karl Hasselström wrote:

> Why the prefix? Wouldn't it be easier to just have one "switch
> branch" prompt that would tab complete existing branch names, and
>
>   * if the user enters the name of an existing branch, just switch to
>     it;
>
>   * if the user enters a name that's not the name of an existing
>     branch, ask for confirmation, and then create the new branch and
>     switch to it.

Reading your code a bit more carefully, I realize that my suggestion
doesn't give you the opportunity to base the new branch on anything
but HEAD. So change the second bullet to

  * if the user enters a name that's not the name of an existing
    branch, display a prompt like this

      Creating new branch "foo". Where should it start?

    Tab complete on existing tags and branches, but accept any
    committish. Create the new branch and switch to it.

This bit of UI could obviously be reused to make create-branch and
create-tag commands that don't switch the current branch.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

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

* Re: [PATCH] Add function to checkout a branch in git.el
  2008-02-13 16:43   ` Karl Hasselström
@ 2008-02-13 18:09     ` Remi Vanicat
  2008-02-13 18:23     ` Sergei Organov
  1 sibling, 0 replies; 14+ messages in thread
From: Remi Vanicat @ 2008-02-13 18:09 UTC (permalink / raw)
  To: Karl Hasselström
  Cc: =?utf-8?q?R=C3=A9mi=20Vanicat?=, git, Alexandre Julliard

M-x git-change-branch checkout branch, and ask for confirmation
if a new one is to be created
One could also use a new submenu in the Git menu for this.
---
Karl Hasselström <kha@treskal.com> writes:

> On 2008-02-13 17:30:02 +0100, Karl Hasselström wrote:
>
>> Why the prefix? Wouldn't it be easier to just have one "switch
>> branch" prompt that would tab complete existing branch names, and

I didn't think of the other way, that seem simpler. Here is a
corrected patch

>   * if the user enters a name that's not the name of an existing
>     branch, display a prompt like this
>
>       Creating new branch "foo". Where should it start?
>
>     Tab complete on existing tags and branches, but accept any
>     committish. Create the new branch and switch to it.
Mmm seem cool, but I have no time for now. Patch are welcome,
otherwise I might look at it this weekend or next week.

Also one might want to do detached head checkout, it wont work for
now, but should not be very hard to do.
-- 
Rémi Vanicat
 contrib/emacs/git.el |   45 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index a8bf0ef..bf0601d 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1138,6 +1138,50 @@ Return the list of files that haven't been handled."
   (when (eq (window-buffer) (current-buffer))
     (shrink-window-if-larger-than-buffer)))
 
+(defun git-list-branch ()
+  "Return a list of available branch"
+  ;; should I check if I'm in a git repository ?
+  (let ((branchs ()))
+    (with-temp-buffer
+      (git-run-command-buffer (current-buffer) "branch")
+      (goto-char (point-min))
+      (while (re-search-forward "^\\([ *]\\) \\([^\n]*\\)$" () t)
+	(push (list (match-string 2)
+		    (string= (match-string 1) "*"))
+	      branchs)))
+    (nreverse branchs)))
+
+(defun git-change-branch (branch &optional new)
+  "Switch to another branch
+
+if new is non-nil, creating it if needed
+otherwise just checkout it"
+  (interactive
+   (let ((branch (completing-read "Branch: " (git-list-branch))))
+     (list branch
+	   (and (not (assoc branch (git-list-branch)))
+		(or (y-or-n-p "create a new branch? ")
+		    (error "branch does not exist"))))))
+  (with-temp-buffer
+    (if new
+	(git-call-process-display-error "checkout" "-b" branch)
+	(git-call-process-display-error "checkout" branch "--"))
+    (goto-char (point-min))))
+
+(defun git-change-new-branch-menu (branch)
+  "Switch to new branch"
+  (interactive "MBranch: ")
+  (git-change-branch branch 't))
+
+(defun git-change-branch-menu-filter (rest)
+  "define the change branch menu"
+  (append
+   (mapcar
+    (lambda (branch)
+      `[,(car branch) (git-change-branch ,(car branch)) t])
+    (git-list-branch))
+   (list ["change to new" git-change-new-branch-menu t])))
+
 (defun git-diff-file ()
   "Diff the marked file(s) against HEAD."
   (interactive)
@@ -1486,6 +1530,7 @@ amended version of it."
 	["Diff Against Merge Head" git-diff-file-merge-head t]
 	["Diff Against Mine" git-diff-file-mine t]
 	["Diff Against Other" git-diff-file-other t])
+      ("Change branch" :filter git-change-branch-menu-filter)
       "--------"
       ["Add File" git-add-file t]
       ["Revert File" git-revert-file t]
-- 
1.5.4.1.101.gacba

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

* Re: [PATCH] Add function to checkout a branch in git.el
  2008-02-13 16:43   ` Karl Hasselström
  2008-02-13 18:09     ` Remi Vanicat
@ 2008-02-13 18:23     ` Sergei Organov
  2008-02-13 21:04       ` Karl Hasselström
  2008-02-16 19:17       ` [patch v2] switching and creating branch, merging and rebasing with Emacs =?utf-8?q?R=C3=A9mi=20Vanicat?=
  1 sibling, 2 replies; 14+ messages in thread
From: Sergei Organov @ 2008-02-13 18:23 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: vanicat, git, Alexandre Julliard

Karl Hasselström <kha@treskal.com> writes:

> On 2008-02-13 17:30:02 +0100, Karl Hasselström wrote:
>
>> Why the prefix? Wouldn't it be easier to just have one "switch
>> branch" prompt that would tab complete existing branch names, and
>>
>>   * if the user enters the name of an existing branch, just switch to
>>     it;
>>
>>   * if the user enters a name that's not the name of an existing
>>     branch, ask for confirmation, and then create the new branch and
>>     switch to it.
>
> Reading your code a bit more carefully, I realize that my suggestion
> doesn't give you the opportunity to base the new branch on anything
> but HEAD. So change the second bullet to
>
>   * if the user enters a name that's not the name of an existing
>     branch, display a prompt like this
>
>       Creating new branch "foo". Where should it start?
>
>     Tab complete on existing tags and branches, but accept any
>     committish. Create the new branch and switch to it.

It still doesn't allow to detach HEAD at arbitrary tag/committish, as
far as I can see.

I believe the interface should be designed more carefully. Here are some
thoughts/suggestions:

1. Let `git-checkout' switch HEAD. It will never create new branches but
   will be able to detach HEAD. Use tab-completion on branch names and
   maybe tags (maybe by inserting tags/ into completion list, and
   switching completion list to tags after tags/ is enterd by user), but
   allow any commitish. Ideally, it will also revert Emacs buffers for
   which working copy files are changed during checkout.

2. Let `git-create-branch' create new branches. It will prompt for a branch
   name, then prompt for starting point with default set to HEAD, and
   create the branch. As it doesn't switch HEAD, it won't touch working
   files.

3. Let `git-branch' create new branch at HEAD and switch to it. This
   will be just a short-cut for common and simple case. Note that this
   will never change working files as newly created branch will match
   HEAD.

4. Reserve C-u prefix for ability to provide arbitrary options to
   underlying GIT commands. For example, it's useful to be able to give
   -m or -f option to "git checkout"; or --track or -f to "git branch".

The "create new branch at arbitrary point and then switch to it" will
then be a two-step operation: either "

((git-create-branch <name> <point>) (git-checkout <name>)

or

((git-checkout <point>) (git-branch <name>))

but that is IMHO reasonable trade-off for interface simplicity, though
yet another function could be defined to do it in one step.

-- Sergei.

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

* Re: [PATCH] Add function to checkout a branch in git.el
  2008-02-13 15:53 [PATCH] Add function to checkout a branch in git.el =?utf-8?q?R=C3=A9mi=20Vanicat?=
  2008-02-13 16:30 ` Karl Hasselström
@ 2008-02-13 18:29 ` Sergei Organov
  1 sibling, 0 replies; 14+ messages in thread
From: Sergei Organov @ 2008-02-13 18:29 UTC (permalink / raw)
  To: vanicat; +Cc: git, Alexandre Julliard

<vanicat@debian.org> writes:
> One can now:
> - checkout an existing branch with M-x git-change-branch
> - create and checkout a new branch with C-u M-x git-change-branch

s/git-change-branch/git-checkout/? I mean is there any reason it is
called differently from GIT's "git checkout"?

Besides, I also think that prefix is not a good idea for this kind of
stuff (see my other reply in this thread).

> - do all this from the Git menu
> ---
> It could also be interesting to add some  key biding for those
>
> Also one might want to update the *git-status* buffer after checkout,
> but this is not done by this patch

Why? Isn't it as simple as calling (git-refresh-status) at the end of
git-change-branch?

>  contrib/emacs/git.el |   45 +++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 45 insertions(+), 0 deletions(-)
>
> diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
> index a8bf0ef..404c8e6 100644
> --- a/contrib/emacs/git.el
> +++ b/contrib/emacs/git.el
> @@ -1138,6 +1138,50 @@ Return the list of files that haven't been handled."
>    (when (eq (window-buffer) (current-buffer))
>      (shrink-window-if-larger-than-buffer)))
>  
> +(defun git-list-branch ()
> +  "Return a list of available branch"

s/branch/branches/

> +  ;; should I check if I'm in a git repository ?
> +  (let ((branchs ()))

s/branchs/branches/


-- Sergei.

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

* Re: [PATCH] Add function to checkout a branch in git.el
  2008-02-13 18:23     ` Sergei Organov
@ 2008-02-13 21:04       ` Karl Hasselström
  2008-02-14 11:47         ` Sergei Organov
  2008-02-16 19:17       ` [patch v2] switching and creating branch, merging and rebasing with Emacs =?utf-8?q?R=C3=A9mi=20Vanicat?=
  1 sibling, 1 reply; 14+ messages in thread
From: Karl Hasselström @ 2008-02-13 21:04 UTC (permalink / raw)
  To: Sergei Organov; +Cc: vanicat, git, Alexandre Julliard

On 2008-02-13 21:23:52 +0300, Sergei Organov wrote:

> Karl Hasselström <kha@treskal.com> writes:
>
> >   * if the user enters a name that's not the name of an existing
> >     branch, display a prompt like this
> >
> >       Creating new branch "foo". Where should it start?
> >
> >     Tab complete on existing tags and branches, but accept any
> >     committish. Create the new branch and switch to it.
>
> It still doesn't allow to detach HEAD at arbitrary tag/committish,
> as far as I can see.

It wouldn't be hard. Just try to interpret the string supplied by the
user as a committish: if successful, check it out; if not, create a
new branch by that name. Of course, this makes it impossible to create
a branch with the same name as an existing committish, but that's
probably OK.

> I believe the interface should be designed more carefully. Here are
> some thoughts/suggestions:

Yes, having different commands that do one job each and do it well
isn't a bad idea either. I like my idea more, but obviously whoever
writes the code gets to decide ...

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

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

* Re: [PATCH] Add function to checkout a branch in git.el
  2008-02-13 21:04       ` Karl Hasselström
@ 2008-02-14 11:47         ` Sergei Organov
  0 siblings, 0 replies; 14+ messages in thread
From: Sergei Organov @ 2008-02-14 11:47 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: vanicat, git, Alexandre Julliard

Karl Hasselström <kha@treskal.com> writes:

> On 2008-02-13 21:23:52 +0300, Sergei Organov wrote:
>
>> Karl Hasselström <kha@treskal.com> writes:
>>
>> >   * if the user enters a name that's not the name of an existing
>> >     branch, display a prompt like this
>> >
>> >       Creating new branch "foo". Where should it start?
>> >
>> >     Tab complete on existing tags and branches, but accept any
>> >     committish. Create the new branch and switch to it.
>>
>> It still doesn't allow to detach HEAD at arbitrary tag/committish,
>> as far as I can see.
>
> It wouldn't be hard. Just try to interpret the string supplied by the
> user as a committish: if successful, check it out; if not, create a
> new branch by that name.

Too much AI for a function, at least to my taste.

> Of course, this makes it impossible to create a branch with the same
> name as an existing committish, but that's probably OK.

I'd say it's probably even desirable. Whatever implementation, I'd at
least check for such a collision and ask for confirmation, provided it's
not very time-consuming.

>
>> I believe the interface should be designed more carefully. Here are
>> some thoughts/suggestions:
>
> Yes, having different commands that do one job each and do it well
> isn't a bad idea either. I like my idea more, but obviously whoever
> writes the code gets to decide ...

Yes, sure. I just wanted to point to alternative approach. Or maybe I'll
get the time to implement it myself, though I'm more interested in
git-merge and git-[fetch|pull]-[merge|rebase] implementation, so that
git.el support at least some of real workflows without resorting to
plain GIT commands.

-- Sergei.

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

* [patch v2] switching and creating branch, merging and rebasing with Emacs
  2008-02-13 18:23     ` Sergei Organov
  2008-02-13 21:04       ` Karl Hasselström
@ 2008-02-16 19:17       ` =?utf-8?q?R=C3=A9mi=20Vanicat?=
  2008-02-16 19:27         ` [PATCH 01/03] Add helper function for branch tag and commitish to git.el Rémi Vanicat
                           ` (2 more replies)
  1 sibling, 3 replies; 14+ messages in thread
From: =?utf-8?q?R=C3=A9mi=20Vanicat?= @ 2008-02-16 19:17 UTC (permalink / raw)
  To: git; +Cc: Karl Hasselström, vanicat, Sergei Organov,
	Alexandre Julliard

I've a new version, in the form of a patch series that follow:
first I add some function for asking user commitish
then some code for checkouting commitish and branching, mostly
following the idea of Sergei,
then some code for merging.

I've look to add rebase, but when thinking about how to do about
conflict and continued rebasing, I feel lazy, and didn't try. As
someone a good idea for the interface?
-- 
Rémi Vanicat

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

* [PATCH 01/03] Add helper function for branch tag and commitish to git.el
  2008-02-16 19:17       ` [patch v2] switching and creating branch, merging and rebasing with Emacs =?utf-8?q?R=C3=A9mi=20Vanicat?=
@ 2008-02-16 19:27         ` Rémi Vanicat
  2008-02-17 18:30           ` Alexandre Julliard
  2008-02-16 19:30         ` [PATCH 02/03] Adding checkout function for commitish in git.el Rémi Vanicat
  2008-02-16 19:35         ` [PATCH 03/03] Adding command for merging " Rémi Vanicat
  2 siblings, 1 reply; 14+ messages in thread
From: Rémi Vanicat @ 2008-02-16 19:27 UTC (permalink / raw)
  To: git; +Cc: Karl Hasselström, Sergei Organov, Alexandre Julliard


---
 contrib/emacs/git.el |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index a8bf0ef..16d9771 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1138,6 +1138,43 @@ Return the list of files that haven't been handled."
   (when (eq (window-buffer) (current-buffer))
     (shrink-window-if-larger-than-buffer)))
 
+(defun git-list-branches (&optional all)
+  "Return an alist of available branches
+if all is non-nil, return all branch, otherwise only local one
+cdr of assoc is non-nil for the current branch
+nil otherwise"
+  (let ((branches ()))
+    (with-temp-buffer
+      (if all
+	  (git-run-command-buffer (current-buffer) "branch" "-a")
+	  (git-run-command-buffer (current-buffer) "branch"))
+      (goto-char (point-min))
+      (while (re-search-forward "^\\([ *]\\) \\([^\n]*\\)$" () t)
+	(push (cons (match-string 2)
+		    (string= (match-string 1) "*"))
+	      branches)))
+    (nreverse branches)))
+
+(defun git-list-tags ()
+  "Return an list of available tags"
+  (let ((tags ()))
+    (with-temp-buffer
+      (git-run-command-buffer (current-buffer) "tag")
+      (goto-char (point-min))
+      (while (re-search-forward "^\\([^\n]+\\)$" () t)
+	(push (match-string 1)
+	      tags)))
+    (nreverse tags)))
+
+(defun git-read-commitish (prompt &optional default)
+  "ask user, with commpletion for a commit, branch, tag or any commitish"
+  (completing-read prompt (list* "HEAD"
+				 "ORIG_HEAD"
+				 "FETCH_HEAD"
+				 (append (git-list-branches t)
+					 (git-list-tags)))
+		   () () () () default))
+
 (defun git-diff-file ()
   "Diff the marked file(s) against HEAD."
   (interactive)
-- 
1.5.4.1.123.gcb68-dirty

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

* [PATCH 02/03] Adding checkout function for commitish in git.el
  2008-02-16 19:17       ` [patch v2] switching and creating branch, merging and rebasing with Emacs =?utf-8?q?R=C3=A9mi=20Vanicat?=
  2008-02-16 19:27         ` [PATCH 01/03] Add helper function for branch tag and commitish to git.el Rémi Vanicat
@ 2008-02-16 19:30         ` Rémi Vanicat
  2008-02-17 18:27           ` Alexandre Julliard
  2008-02-16 19:35         ` [PATCH 03/03] Adding command for merging " Rémi Vanicat
  2 siblings, 1 reply; 14+ messages in thread
From: Rémi Vanicat @ 2008-02-16 19:30 UTC (permalink / raw)
  To: git; +Cc: Karl Hasselström, Sergei Organov, Alexandre Julliard

M-x git-checkout ask for a commitish, and checkout it as in
  git checkout commitish --
  key binding: "C"
M-x git-branch ask for the name of a new branch, create it and
checkout it as in
  git checkout -b name
  key binding: "b"
M-x git-create-branch ask for a new branchname, a startpoint (a
commitish) and create a new branch as in
  git branch branchname startpoint
  key binding "B"
A menu is also available for just switching branch
---
The main problem that I still see, is the error message when one try
to checkout a branch/tag... that doesn't exist: it is a cryptic error
message... 

 contrib/emacs/git.el |   42 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index 16d9771..f180421 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1175,6 +1175,44 @@ nil otherwise"
 					 (git-list-tags)))
 		   () () () () default))
 
+(defun git-checkout (branch &optional merge)
+  "checkout a branch, tag, or any commitish
+
+use a prefix arg if git should merge while checking out"
+  (interactive
+   (list (git-read-commitish "Branch: ")
+	 current-prefix-arg))
+  (let ((args (list branch "--")))
+    (if merge (push "-m" args))
+    (if (apply #'git-call-process-display-error "checkout" args)
+	(git-refresh-status))))
+
+(defun git-branch (branch)
+  "branch from current commit and checkout the new branch"
+  (interactive "MBranch: ")
+  (if (git-call-process-display-error "checkout" "-b" branch)
+      (git-refresh-status)))
+
+(defun git-create-branch (branch start-point)
+  "create a new branch named [branch] from the [start-point]"
+  (interactive
+   (list (read-string "New branch: ")
+	 (git-read-commitish "Start point(HEAD): " "HEAD")))
+  (git-call-process-display-error "branch" branch start-point))
+
+(defun git-checkout-menu-filter (rest)
+  "define the change branch menu"
+  (append
+   (mapcar
+    (lambda (branch)
+      `[,(car branch)
+	 (git-checkout ,(car branch))
+	 :style radio
+	 :selected ,(cdr branch)])
+    (git-list-branches))
+   (list ["checkout any commitish" git-checkout t]
+	 ["change to new" git-branch t])))
+
 (defun git-diff-file ()
   "Diff the marked file(s) against HEAD."
   (interactive)
@@ -1466,6 +1504,9 @@ amended version of it."
     (define-key map "a"   'git-add-file)
     (define-key map "c"   'git-commit-file)
     (define-key map "\C-c" commit-map)
+    (define-key map "C"   'git-checkout)
+    (define-key map "b"   'git-branch)
+    (define-key map "B"   'git-create-branch)
     (define-key map "d"    diff-map)
     (define-key map "="   'git-diff-file)
     (define-key map "f"   'git-find-file)
@@ -1513,6 +1554,7 @@ amended version of it."
     `("Git"
       ["Refresh" git-refresh-status t]
       ["Commit" git-commit-file t]
+      ("Checkout Branch" :filter git-checkout-menu-filter)
       ("Merge"
 	["Next Unmerged File" git-next-unmerged-file t]
 	["Prev Unmerged File" git-prev-unmerged-file t]
-- 
1.5.4.1.123.gcb68-dirty


-- 
Rémi Vanicat

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

* [PATCH 03/03] Adding command for merging in git.el
  2008-02-16 19:17       ` [patch v2] switching and creating branch, merging and rebasing with Emacs =?utf-8?q?R=C3=A9mi=20Vanicat?=
  2008-02-16 19:27         ` [PATCH 01/03] Add helper function for branch tag and commitish to git.el Rémi Vanicat
  2008-02-16 19:30         ` [PATCH 02/03] Adding checkout function for commitish in git.el Rémi Vanicat
@ 2008-02-16 19:35         ` Rémi Vanicat
  2 siblings, 0 replies; 14+ messages in thread
From: Rémi Vanicat @ 2008-02-16 19:35 UTC (permalink / raw)
  To: git; +Cc: Karl Hasselström, Sergei Organov, Alexandre Julliard

M-x git-merge will ask for an commitish, and merge with it.
A new submenu is also available for merging with local and remote
branch.
---
The problem here, which is similar to the one that exist now when one
merge from outside Emacs, is that in case of conflict, Emacs doesn't
look to the index, and so, when one commit the resolved conflict,
one might forget to select all file that should be selected for the
commit to be what is needed.

This problem could be even worse with rebasing, as rebasing is a more
destructive action than merging.


 contrib/emacs/git.el |   22 +++++++++++++++++++++-
 1 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index f180421..60553d3 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1213,6 +1213,25 @@ use a prefix arg if git should merge while checking out"
    (list ["checkout any commitish" git-checkout t]
 	 ["change to new" git-branch t])))
 
+(defun git-merge (commitish)
+  "merge with commitish
+
+Note that in case of conflict, after resolving everty conflict,
+one have to select every concerned file before commiting"
+  (interactive (list (git-read-commitish "Merge with: ")))
+  (git-call-process-display-error "merge" commitish)
+  (git-refresh-status))
+
+(defun git-merge-menu-filter (rest)
+  "define the merge branch menu"
+  (append
+   (mapcar
+    (lambda (branch)
+      `[,(car branch)
+	 (git-merge ,(car branch)) :visible ,(not (cdr branch))])
+    (git-list-branches :all))
+   (list ["merge with any commitish" git-merge t])))
+
 (defun git-diff-file ()
   "Diff the marked file(s) against HEAD."
   (interactive)
@@ -1555,7 +1574,8 @@ amended version of it."
       ["Refresh" git-refresh-status t]
       ["Commit" git-commit-file t]
       ("Checkout Branch" :filter git-checkout-menu-filter)
-      ("Merge"
+      ("Merge" :filter git-merge-menu-filter)
+      ("Resolve Merge"
 	["Next Unmerged File" git-next-unmerged-file t]
 	["Prev Unmerged File" git-prev-unmerged-file t]
 	["Mark as Resolved" git-resolve-file t]
-- 
1.5.4.1.123.gcb68-dirty

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

* Re: [PATCH 02/03] Adding checkout function for commitish in git.el
  2008-02-16 19:30         ` [PATCH 02/03] Adding checkout function for commitish in git.el Rémi Vanicat
@ 2008-02-17 18:27           ` Alexandre Julliard
  0 siblings, 0 replies; 14+ messages in thread
From: Alexandre Julliard @ 2008-02-17 18:27 UTC (permalink / raw)
  To: Rémi Vanicat; +Cc: git, Karl Hasselström, Sergei Organov

Rémi Vanicat <vanicat@debian.org> writes:

> M-x git-checkout ask for a commitish, and checkout it as in
>   git checkout commitish --
>   key binding: "C"
> M-x git-branch ask for the name of a new branch, create it and
> checkout it as in
>   git checkout -b name
>   key binding: "b"
> M-x git-create-branch ask for a new branchname, a startpoint (a
> commitish) and create a new branch as in
>   git branch branchname startpoint
>   key binding "B"
> A menu is also available for just switching branch

My idea was to put commands that act on commits instead of files on the
C-c prefix, for instance amend-commit is on C-c C-a, I have a
preliminary cherry-pick implementation that I put on C-C C-p, then we
could have git-checkout on C-c C-o, git-branch on C-c C-b, git-merge on
C-c C-m. Otherwise we'll soon run out of single letter bindings.

Also for more complex operations like git-create-branch we may want
another prefix, as there would probably be more branch manipulations
commands.  For instance something like "B C" for create-branch, "B D"
for delete-branch, "B M" for move-branch etc.

-- 
Alexandre Julliard
julliard@winehq.org

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

* Re: [PATCH 01/03] Add helper function for branch tag and commitish to git.el
  2008-02-16 19:27         ` [PATCH 01/03] Add helper function for branch tag and commitish to git.el Rémi Vanicat
@ 2008-02-17 18:30           ` Alexandre Julliard
  0 siblings, 0 replies; 14+ messages in thread
From: Alexandre Julliard @ 2008-02-17 18:30 UTC (permalink / raw)
  To: Rémi Vanicat; +Cc: git, Karl Hasselström, Sergei Organov

Rémi Vanicat <vanicat@debian.org> writes:

> +(defun git-list-branches (&optional all)
> +  "Return an alist of available branches
> +if all is non-nil, return all branch, otherwise only local one
> +cdr of assoc is non-nil for the current branch
> +nil otherwise"
> +  (let ((branches ()))
> +    (with-temp-buffer
> +      (if all
> +	  (git-run-command-buffer (current-buffer) "branch" "-a")
> +	  (git-run-command-buffer (current-buffer) "branch"))
> +      (goto-char (point-min))
> +      (while (re-search-forward "^\\([ *]\\) \\([^\n]*\\)$" () t)
> +	(push (cons (match-string 2)
> +		    (string= (match-string 1) "*"))
> +	      branches)))
> +    (nreverse branches)))

git-run-command-buffer isn't really what you want to use here, look at
how other functions that use a temp-buffer do it. Also that alist thing
is ugly, there are better ways of finding the current branch if we need
it. Besides, you probably want to use git-for-each-ref instead of
git-branch, git-branch is a bit too porcelainish IMO.

-- 
Alexandre Julliard
julliard@winehq.org

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

end of thread, other threads:[~2008-02-17 18:31 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-13 15:53 [PATCH] Add function to checkout a branch in git.el =?utf-8?q?R=C3=A9mi=20Vanicat?=
2008-02-13 16:30 ` Karl Hasselström
2008-02-13 16:43   ` Karl Hasselström
2008-02-13 18:09     ` Remi Vanicat
2008-02-13 18:23     ` Sergei Organov
2008-02-13 21:04       ` Karl Hasselström
2008-02-14 11:47         ` Sergei Organov
2008-02-16 19:17       ` [patch v2] switching and creating branch, merging and rebasing with Emacs =?utf-8?q?R=C3=A9mi=20Vanicat?=
2008-02-16 19:27         ` [PATCH 01/03] Add helper function for branch tag and commitish to git.el Rémi Vanicat
2008-02-17 18:30           ` Alexandre Julliard
2008-02-16 19:30         ` [PATCH 02/03] Adding checkout function for commitish in git.el Rémi Vanicat
2008-02-17 18:27           ` Alexandre Julliard
2008-02-16 19:35         ` [PATCH 03/03] Adding command for merging " Rémi Vanicat
2008-02-13 18:29 ` [PATCH] Add function to checkout a branch " Sergei Organov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).