threads / patch / 28163

patchgitk: Allow commit editing

Subject: [PATCH] gitk: Allow commit editing

## tl;dr

10 messages between Aug 19, 2011 and Sep 13, 2011. Diffs are folded; open one to read it.

replies: 9people: 3as markdown or json

Michal Sojka· Aug 19, 2011, 12:23 UTC · lore

Re: [PATCH RFC] gitk: Allow commit editing

On Thu, 18 Aug 2011, Jeff King wrote:
Show 17 quoted lines
> On Wed, Aug 17, 2011 at 09:56:11PM +0200, Michal Sojka wrote:
> 
> > Hi, this is a proof of concept patch that allows editing of commits
> > from gitk. I often review patches before pushing in gitk and if I
> > would like to have an easy way of fixing typos in commit messages etc.
> > 
> > So the patch adds "Edit this commit" item to gitk's context menu and
> > the actual editing is done by non-interactively invoking interactive
> > rebase :-) and git gui.
> 
> Invoking rebase behind the scenes makes me very nervous. In particular:
> 
>   1. There is nothing to indicate to the user that they are rewriting a
>      string of commits, which is going to wreak havoc if any of the
>      commits have been published elsewhere (either pushed somewhere, or
>      even present in another local branch). I.e., rebasing generally
>      needs to be a conscious decision of the user.

I added a warning if the edited commit is contained in a remote branch. Would you consider this sufficient?

Show 5 quoted lines
>   2. Even if you accept the hazard of rewriting commits, you don't pass
>      "-p" to rebase. So it will linearize your history. I don't know how
>      robust "-p" is these days, and if it's up to the challenge of
>      people using it to rebase potentially large segments of complex
>      history.

I added "-p" to rebase. I do not know about the robustness of "-p" as well, but is anything goes wrong during the rebase, git rebase --abort hopefully reverts everything.

> So I think your idea is sane, and if you use it appropriately (by
> editing commits in recent-ish linear stretches of history) your patch
> works fine. But I really worry that it is going to be a problem for less
> clueful users to stumble across in the menu.
See the next version of the patch in a follow-up mail.
-Michal
Michal Sojka· Aug 19, 2011, 12:25 UTC · re: Michal Sojka · lore

I often use gitk to review patches before pushing them and would like to have an easy way of fixing typos in commit messages. The current approach if copying the commitid, switching to terminal, invoking git rebase -i, editing the commit and switching back to gitk is a way too complicated just for chaning a single letter.

This patch adds "Edit this commit" item to gitk's context menu which invokes interactive rebase in a non-interactive way :-). git gui is used to actually edit the commit.

The user is warned if the commit that is going to be edited is contained in a remote branch.

Signed-off-by: Michal Sojka <sojka@os.inf.tu-dresden.de>
---
 gitk-git/gitk |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)
Show changes to gitk-git/gitk +31 −0
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 4cde0c4..83b3307 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -2487,6 +2487,7 @@ proc makewindow {} {
     makemenu $rowctxmenu {
 	{mc "Diff this -> selected" command {diffvssel 0}}
 	{mc "Diff selected -> this" command {diffvssel 1}}
+	{mc "Edit this commit" command edit_commit}
 	{mc "Make patch" command mkpatch}
 	{mc "Create tag" command mktag}
 	{mc "Write commit to file" command writecommit}
@@ -9102,6 +9103,36 @@ proc cherrypick {} {
     notbusy cherrypick
 }
 
+proc edit_commit {} {
+    global rowmenuid selectedline
+
+    if {[exec git branch -r --contains=$rowmenuid] ne {}} {
+	if {![confirm_popup [mc "The commit you are going to edit appears in at least one\
+				 remote branch. It is a bad idea to change a branch that is\
+				 possibly used by other people. See git-rebase(1) for details.\n\n\
+				 Do you want to continue?"]]} return }
+
+    nowbusy edit [mc "Editing commit"]
+    if {[catch {exec sh -c "(GIT_EDITOR='sed -ie 1s/^pick/edit/' git rebase -p -i $rowmenuid^ && git gui citool --amend) 2>&1"} err]} {
+	notbusy edit
+	error_popup $err
+	exec git rebase --abort
+	return
+    }
+    set newcommit [exec git rev-parse HEAD]
+    if {[catch {exec sh -c "git rebase --continue 2>&1"} err]} {
+	notbusy edit
+	error_popup $err
+	exec git rebase --abort
+	return
+    }
+    updatecommits
+    # XXX How to select the edited commit? This doesn't work.
+    selbyid $newcommit
+    notbusy edit
+}
+
+
 proc resethead {} {
     global mainhead rowmenuid confirm_ok resettype NS
 
-- 
1.7.5.4
Jeff King· Aug 25, 2011, 03:14 UTC · re: Michal Sojka · lore

Re: [PATCH] gitk: Allow commit editing

On Fri, Aug 19, 2011 at 02:25:53PM +0200, Michal Sojka wrote:
Show 5 quoted lines
> +    if {[exec git branch -r --contains=$rowmenuid] ne {}} {
> +	if {![confirm_popup [mc "The commit you are going to edit appears in at least one\
> +				 remote branch. It is a bad idea to change a branch that is\
> +				 possibly used by other people. See git-rebase(1) for details.\n\n\
> +				 Do you want to continue?"]]} return }

We frown on using porcelain like "git branch" here, because it was not meant to be scriptable (i.e., its behavior may change in future releases).

As I mentioned elsewhere, I think you really want to see whether the commit is referenced by any other ref, not just branches; if it is, then the rebase is potentially problematic. You can do that with something like:

  us=`git symbolic-ref HEAD`
  git for-each-ref --format='%(refname)' |
  while read ref; do
    test "$ref" = $us" && continue
    echo "^$ref"
  done |
  git rev-list HEAD --stdin

That will give a list of commits found only on HEAD and nowhere else (i.e., those which are safe to rebase). If your commit is among them, then it's safe.

Speaking of which, notice that I used HEAD here. What happens with your patch if I do:

  $ git checkout foo
  $ gitk bar
and select a commit to edit that is not in "foo"?
-Peff
Michal Sojka· Aug 25, 2011, 13:15 UTC · re: Jeff King · lore

Re: [PATCH v3] gitk: Allow commit editing

On Thu, 25 Aug 2011, Jeff King wrote:
Show 28 quoted lines
> On Fri, Aug 19, 2011 at 02:25:53PM +0200, Michal Sojka wrote:
> 
> > +    if {[exec git branch -r --contains=$rowmenuid] ne {}} {
> > +	if {![confirm_popup [mc "The commit you are going to edit appears in at least one\
> > +				 remote branch. It is a bad idea to change a branch that is\
> > +				 possibly used by other people. See git-rebase(1) for details.\n\n\
> > +				 Do you want to continue?"]]} return }
> 
> We frown on using porcelain like "git branch" here, because it was not
> meant to be scriptable (i.e., its behavior may change in future
> releases).
> 
> As I mentioned elsewhere, I think you really want to see whether the
> commit is referenced by any other ref, not just branches; if it is, then
> the rebase is potentially problematic. You can do that with something
> like:
> 
>   us=`git symbolic-ref HEAD`
>   git for-each-ref --format='%(refname)' |
>   while read ref; do
>     test "$ref" = $us" && continue
>     echo "^$ref"
>   done |
>   git rev-list HEAD --stdin
> 
> That will give a list of commits found only on HEAD and nowhere else
> (i.e., those which are safe to rebase). If your commit is among them,
> then it's safe.

I implemented something like you ontlined above (see below). Instead of rev-listing HEAD, I use the commit id to be edited. This way I don't have to find the commit in the returned list, but I only check whether the list is empty or not.

Additionally, besides skiping HEAD ref, I also skip refs/stash. Rebasing before stash should not (I hope) cause any problems and therefore it is not necessary to warn the user.

Show 7 quoted lines
> Speaking of which, notice that I used HEAD here. What happens with your
> patch if I do:
> 
>   $ git checkout foo
>   $ gitk bar
> 
> and select a commit to edit that is not in "foo"?

I added a check for this. If this is detected, error message is displayed and no edit is possible.

The other changes in this version are:
- added --no-autosquash to rebase invocation
- fixed indexes of menu entries following the new edit entry.

Regards, -Michal

--8<---------------cut here---------------start------------->8--- I often use gitk to review patches before pushing them out and I would like to have an easy way to edit commits. The current approach with copying the commitid, switching to terminal, invoking git rebase -i, editing the commit and switching back to gitk is a way too complicated just for changing a single letter in the commit message or removing a debug printf().

This patch adds "Edit this commit" item to gitk's context menu which invokes interactive rebase in a non-interactive way :-). git gui is used to actually edit the commit.

Besides editing the commit message, splitting of commits, as described in git-rebase(1), is also supported.

The user is warned if the commit to be edited is contained in another ref besides the current branch and the stash (e.g. in a remote branch). Additionally, error box is displayed if the user attempts to edit a commit not contained in the current branch.

Signed-off-by: Michal Sojka <sojka@os.inf.tu-dresden.de>
---
 gitk-git/gitk |   71 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 67 insertions(+), 4 deletions(-)
Show changes to gitk-git/gitk +67 −4
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 4cde0c4..0968efa 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -2487,6 +2487,7 @@ proc makewindow {} {
     makemenu $rowctxmenu {
 	{mc "Diff this -> selected" command {diffvssel 0}}
 	{mc "Diff selected -> this" command {diffvssel 1}}
+	{mc "Edit this commit" command edit_commit}
 	{mc "Make patch" command mkpatch}
 	{mc "Create tag" command mktag}
 	{mc "Write commit to file" command writecommit}
@@ -8428,18 +8429,18 @@ proc rowmenu {x y id} {
     if {$id ne $nullid && $id ne $nullid2} {
 	set menu $rowctxmenu
 	if {$mainhead ne {}} {
-	    $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
+	    $menu entryconfigure 8 -label [mc "Reset %s branch to here" $mainhead] -state normal
 	} else {
-	    $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
+	    $menu entryconfigure 8 -label [mc "Detached head: can't reset" $mainhead] -state disabled
 	}
 	if {[info exists markedid] && $markedid ne $id} {
-	    $menu entryconfigure 9 -state normal
 	    $menu entryconfigure 10 -state normal
 	    $menu entryconfigure 11 -state normal
+	    $menu entryconfigure 12 -state normal
 	} else {
-	    $menu entryconfigure 9 -state disabled
 	    $menu entryconfigure 10 -state disabled
 	    $menu entryconfigure 11 -state disabled
+	    $menu entryconfigure 12 -state disabled
 	}
     } else {
 	set menu $fakerowmenu
@@ -9102,6 +9103,68 @@ proc cherrypick {} {
     notbusy cherrypick
 }
 
+proc rebase_ok {id} {
+    if {[exec git merge-base $id HEAD] ne $id} {
+	error_popup [mc "You cannot edit commits outside of the current branch."]
+	return 0
+    }
+    set headref [exec git symbolic-ref HEAD]
+    set allrefs [split [exec git for-each-ref --format=%(refname)] "\n"]
+    set otherrefs {}
+    set otherrefsneg ""
+    foreach ref $allrefs {
+	if {$ref eq "refs/stash" || $ref eq $headref} continue
+	set otherrefsneg "$otherrefsneg^$ref\n"
+    }
+
+    # Check whether some other refs contain the commit to be edited
+    if {[exec git rev-list --stdin $id << $otherrefsneg] eq {}} {
+	if { [confirm_popup [mc "The commit you are going to edit is contained in another, possibly non-local, ref (e.g. branch or tag).\
+				It is a bad idea to change a ref that is possibly used by other people. See git-rebase(1) for details.\n\n\
+				Do you want to continue?"]]} {
+	    return 1
+	} else {
+	    return 0
+	}
+    }
+    return 1
+}
+
+proc edit_commit {} {
+    global rowmenuid selectedline
+
+    if {![rebase_ok $rowmenuid]} return
+
+    nowbusy edit [mc "Editing commit"]
+    if {[catch {exec sh -c "(GIT_EDITOR='sed -ie 1s/^pick/edit/' git rebase -p -i --no-autosquash $rowmenuid^ && git gui citool --amend) 2>&1"} err]} {
+	notbusy edit
+	error_popup $err
+	exec git rebase --abort
+	return
+    }
+    set newcommit [exec git rev-parse HEAD]
+    while {[catch {exec sh -c "git diff-index --quiet --cached HEAD && git diff-files --quiet"} err]} {
+	if {[confirm_popup [mc "There are uncommited changes in the working tree or in the index.\
+				Do you want to create a new commit (OK) or discard them (Cancel)?"]]} {
+	    catch {exec git gui citool} err;
+	    # In case of error (i.e. the user did not commit anything), we just ask him again
+	} else {
+	    exec git reset --hard
+	}
+    }
+    if {[catch {exec sh -c "git rebase --continue 2>&1"} err]} {
+	notbusy edit
+	error_popup $err
+	exec git rebase --abort
+	return
+    }
+    updatecommits
+    # XXX How to select the edited commit? This doesn't work.
+    selbyid $newcommit
+    notbusy edit
+}
+
+
 proc resethead {} {
     global mainhead rowmenuid confirm_ok resettype NS
 
-- 
1.7.5.4

--8<---------------cut here---------------end--------------->8---
Jeff King· Aug 25, 2011, 17:30 UTC · re: Michal Sojka · lore

Re: [PATCH v3] gitk: Allow commit editing

On Thu, Aug 25, 2011 at 03:15:42PM +0200, Michal Sojka wrote:
> I implemented something like you ontlined above (see below). Instead of
> rev-listing HEAD, I use the commit id to be edited. This way I don't
> have to find the commit in the returned list, but I only check whether
> the list is empty or not.

Yeah, that makes sense. Technically you are also rewriting every commit _after_ the commit in question, so you want to be sure that those aren't included elsewhere, too. But by definition, any ref which includes them must also include the commit in question, so I think your test is sufficient.

> Additionally, besides skiping HEAD ref, I also skip refs/stash. Rebasing
> before stash should not (I hope) cause any problems and therefore it is
> not necessary to warn the user.
Yes, that makes sense to me, too.
Show 10 quoted lines
> > Speaking of which, notice that I used HEAD here. What happens with your
> > patch if I do:
> > 
> >   $ git checkout foo
> >   $ gitk bar
> > 
> > and select a commit to edit that is not in "foo"?
> 
> I added a check for this. If this is detected, error message is
> displayed and no edit is possible.

I was going to suggest that we could actually do the rebase on "bar", but that is probably too much complexity hiding behind the user's back (not to mention that there are lots of corner cases where figuring out the right branch is tough, like "gitk <sha1>").

> The other changes in this version are:
> - added --no-autosquash to rebase invocation
Yeah, that is probably a good idea.
Show 6 quoted lines
> +    # Check whether some other refs contain the commit to be edited
> +    if {[exec git rev-list --stdin $id << $otherrefsneg] eq {}} {
> +	if { [confirm_popup [mc "The commit you are going to edit is contained in another, possibly non-local, ref (e.g. branch or tag).\
> +				It is a bad idea to change a ref that is possibly used by other people. See git-rebase(1) for details.\n\n\
> +				Do you want to continue?"]]} {
> +	    return 1

Minor micro-optimization: this can be "git rev-list -1". You only care if it produces the one commit, so that's sufficient. Without "-1", git will keep reporting commits all the way down to the merge base with some other ref.

Another question I had while thinking about whether or not this whole idea is sane: what happens with conflicts in later commits that are caused by your amended changes? Rebase will complain to the terminal, no? Which the user may or may not even see, depending on how they started gitk.

-Peff
Michal Sojka· Aug 27, 2011, 12:31 UTC · re: Jeff King · lore

[PATCH v4] gitk: Allow commit editing

On Thu, 25 Aug 2011, Jeff King wrote:
Show 12 quoted lines
> On Thu, Aug 25, 2011 at 03:15:42PM +0200, Michal Sojka wrote:
> > +    # Check whether some other refs contain the commit to be edited
> > +    if {[exec git rev-list --stdin $id << $otherrefsneg] eq {}} {
> > +	if { [confirm_popup [mc "The commit you are going to edit is contained in another, possibly non-local, ref (e.g. branch or tag).\
> > +				It is a bad idea to change a ref that is possibly used by other people. See git-rebase(1) for details.\n\n\
> > +				Do you want to continue?"]]} {
> > +	    return 1
> 
> Minor micro-optimization: this can be "git rev-list -1". You only care
> if it produces the one commit, so that's sufficient. Without "-1", git
> will keep reporting commits all the way down to the merge base with some
> other ref.
Here is a new version with the micro-optimization.

Another minor change is that this patch now applies to gitk repo (http://git.kernel.org/pub/scm/gitk/gitk.git) instead of the main git repo.

-Michal

--8<---------------cut here---------------start------------->8--- I often use gitk to review patches before pushing them out and I would like to have an easy way to edit commits. The current approach with copying the commitid, switching to terminal, invoking git rebase -i, editing the commit and switching back to gitk is a way too complicated just for changing a single letter in the commit message or removing a debug printf().

This patch adds "Edit this commit" item to gitk's context menu which invokes interactive rebase in a non-interactive way :-). git gui is used to actually edit the commit.

Besides editing the commit message, splitting of commits, as described in git-rebase(1), is also supported.

The user is warned if the commit to be edited is contained in another ref besides the current branch and the stash (e.g. in a remote branch). Additionally, error box is displayed if the user attempts to edit a commit not contained in the current branch.

Signed-off-by: Michal Sojka <sojka@os.inf.tu-dresden.de>
---
 gitk |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 67 insertions(+), 4 deletions(-)
Show changes to gitk +67 −4
diff --git a/gitk b/gitk
index a701e0d..1ca2d00 100755
--- a/gitk
+++ b/gitk
@@ -2481,6 +2481,7 @@ proc makewindow {} {
     makemenu $rowctxmenu {
 	{mc "Diff this -> selected" command {diffvssel 0}}
 	{mc "Diff selected -> this" command {diffvssel 1}}
+	{mc "Edit this commit" command edit_commit}
 	{mc "Make patch" command mkpatch}
 	{mc "Create tag" command mktag}
 	{mc "Write commit to file" command writecommit}
@@ -8445,18 +8446,18 @@ proc rowmenu {x y id} {
     if {$id ne $nullid && $id ne $nullid2} {
 	set menu $rowctxmenu
 	if {$mainhead ne {}} {
-	    $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
+	    $menu entryconfigure 8 -label [mc "Reset %s branch to here" $mainhead] -state normal
 	} else {
-	    $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
+	    $menu entryconfigure 8 -label [mc "Detached head: can't reset" $mainhead] -state disabled
 	}
 	if {[info exists markedid] && $markedid ne $id} {
-	    $menu entryconfigure 9 -state normal
 	    $menu entryconfigure 10 -state normal
 	    $menu entryconfigure 11 -state normal
+	    $menu entryconfigure 12 -state normal
 	} else {
-	    $menu entryconfigure 9 -state disabled
 	    $menu entryconfigure 10 -state disabled
 	    $menu entryconfigure 11 -state disabled
+	    $menu entryconfigure 12 -state disabled
 	}
     } else {
 	set menu $fakerowmenu
@@ -9120,6 +9121,68 @@ proc cherrypick {} {
     notbusy cherrypick
 }
 
+proc rebase_ok {id} {
+    if {[exec git merge-base $id HEAD] ne $id} {
+	error_popup [mc "You cannot edit commits outside of the current branch."]
+	return 0
+    }
+    set headref [exec git symbolic-ref HEAD]
+    set allrefs [split [exec git for-each-ref --format=%(refname)] "\n"]
+    set otherrefs {}
+    set otherrefsneg ""
+    foreach ref $allrefs {
+	if {$ref eq "refs/stash" || $ref eq $headref} continue
+	set otherrefsneg "$otherrefsneg^$ref\n"
+    }
+
+    # Check whether some other refs contain the commit to be edited
+    if {[exec git rev-list --stdin $id --max-count=1 << $otherrefsneg] eq {}} {
+	if { [confirm_popup [mc "The commit you are going to edit is contained in another, possibly non-local, ref (e.g. branch or tag).\
+				It is a bad idea to change a ref that is possibly used by other people. See git-rebase(1) for details.\n\n\
+				Do you want to continue?"]]} {
+	    return 1
+	} else {
+	    return 0
+	}
+    }
+    return 1
+}
+
+proc edit_commit {} {
+    global rowmenuid selectedline
+
+    if {![rebase_ok $rowmenuid]} return
+
+    nowbusy edit [mc "Editing commit"]
+    if {[catch {exec sh -c "(GIT_EDITOR='sed -ie 1s/^pick/edit/' git rebase -p -i --no-autosquash $rowmenuid^ && git gui citool --amend) 2>&1"} err]} {
+	notbusy edit
+	error_popup $err
+	exec git rebase --abort
+	return
+    }
+    set newcommit [exec git rev-parse HEAD]
+    while {[catch {exec sh -c "git diff-index --quiet --cached HEAD && git diff-files --quiet"} err]} {
+	if {[confirm_popup [mc "There are uncommited changes in the working tree or in the index.\
+				Do you want to create a new commit (OK) or discard them (Cancel)?"]]} {
+	    catch {exec git gui citool} err;
+	    # In case of error (i.e. the user did not commit anything), we just ask him again
+	} else {
+	    exec git reset --hard
+	}
+    }
+    if {[catch {exec sh -c "git rebase --continue 2>&1"} err]} {
+	notbusy edit
+	error_popup $err
+	exec git rebase --abort
+	return
+    }
+    updatecommits
+    # XXX How to select the edited commit? This doesn't work.
+    selbyid $newcommit
+    notbusy edit
+}
+
+
 proc resethead {} {
     global mainhead rowmenuid confirm_ok resettype NS
 
-- 
1.7.5.4

--8<---------------cut here---------------end--------------->8---
Jeff King· Sep 7, 2011, 20:10 UTC · re: Michal Sojka · lore

Re: [PATCH v4] gitk: Allow commit editing

On Sat, Aug 27, 2011 at 02:31:02PM +0200, Michal Sojka wrote:
Show 5 quoted lines
> Here is a new version with the micro-optimization.
> 
> Another minor change is that this patch now applies to gitk repo
> (http://git.kernel.org/pub/scm/gitk/gitk.git) instead of the main git
> repo.

Thanks. This version fixes most of my complaints and looks reasonable sane, as long as you accept the idea that starting an interactive rebase behind the scenes is sane. I'm still not 100% convinced. But then, I am not a big gitk user, either (I like visualizing with it, but I rarely want to do anything interactive). So I'll leave Paul and anyone else to argue or make a decision on that count.

-Peff
Paul Mackerras· Sep 8, 2011, 20:59 UTC · re: Michal Sojka · lore

Re: [PATCH v4] gitk: Allow commit editing

On Sat, Aug 27, 2011 at 02:31:02PM +0200, Michal Sojka wrote:
Show 27 quoted lines
> Here is a new version with the micro-optimization.
> 
> Another minor change is that this patch now applies to gitk repo
> (http://git.kernel.org/pub/scm/gitk/gitk.git) instead of the main git
> repo.
> 
> -Michal
> 
> --8<---------------cut here---------------start------------->8---
> I often use gitk to review patches before pushing them out and I would
> like to have an easy way to edit commits. The current approach with
> copying the commitid, switching to terminal, invoking git rebase -i,
> editing the commit and switching back to gitk is a way too complicated
> just for changing a single letter in the commit message or removing a
> debug printf().
> 
> This patch adds "Edit this commit" item to gitk's context menu which
> invokes interactive rebase in a non-interactive way :-). git gui is
> used to actually edit the commit.
> 
> Besides editing the commit message, splitting of commits, as described
> in git-rebase(1), is also supported.
> 
> The user is warned if the commit to be edited is contained in another
> ref besides the current branch and the stash (e.g. in a remote
> branch). Additionally, error box is displayed if the user attempts to
> edit a commit not contained in the current branch.

I have to say that this patch makes me pretty nervous. I can see the attractiveness of the feature, but I don't like making gitk unresponsive for a potentially long time, i.e. until git gui exits. It may not be clear to users that the reason gitk isn't responding is because some other git gui window is still running.

Also, if some subsequent commit no longer applies because of the changes you make to a commit, it's going to abort the rebase completely and thus lose the changes you made. That could be annoying.

I usually do this by starting a new branch just before the commit I want to change and then use a combination of the cherry-pick menu item and git commit --amend. Maybe something to make that simpler for users would be good, i.e. automate it a bit but still have it be a step-by-step process if necessary. Part of the problem of course is that neither gitk nor git gui are really designed to be an editing environment. In fact you really want an edit/compile/test environment so you don't introduce new bugs.

Paul.
Michal Sojka· Sep 13, 2011, 23:11 UTC · re: Paul Mackerras · lore

Re: [PATCH v4] gitk: Allow commit editing

On Thu, 08 Sep 2011, Paul Mackerras wrote:
Show 34 quoted lines
> On Sat, Aug 27, 2011 at 02:31:02PM +0200, Michal Sojka wrote:
> > Here is a new version with the micro-optimization.
> > 
> > Another minor change is that this patch now applies to gitk repo
> > (http://git.kernel.org/pub/scm/gitk/gitk.git) instead of the main git
> > repo.
> > 
> > -Michal
> > 
> > --8<---------------cut here---------------start------------->8---
> > I often use gitk to review patches before pushing them out and I would
> > like to have an easy way to edit commits. The current approach with
> > copying the commitid, switching to terminal, invoking git rebase -i,
> > editing the commit and switching back to gitk is a way too complicated
> > just for changing a single letter in the commit message or removing a
> > debug printf().
> > 
> > This patch adds "Edit this commit" item to gitk's context menu which
> > invokes interactive rebase in a non-interactive way :-). git gui is
> > used to actually edit the commit.
> > 
> > Besides editing the commit message, splitting of commits, as described
> > in git-rebase(1), is also supported.
> > 
> > The user is warned if the commit to be edited is contained in another
> > ref besides the current branch and the stash (e.g. in a remote
> > branch). Additionally, error box is displayed if the user attempts to
> > edit a commit not contained in the current branch.
> 
> I have to say that this patch makes me pretty nervous.  I can see the
> attractiveness of the feature, but I don't like making gitk
> unresponsive for a potentially long time, i.e. until git gui exits.
> It may not be clear to users that the reason gitk isn't responding is
> because some other git gui window is still running.
I understand this. See below for a possible solution.
 
> Also, if some subsequent commit no longer applies because of the
> changes you make to a commit, it's going to abort the rebase
> completely and thus lose the changes you made.  That could be
> annoying.

Agreed. A solution could be to create a ref called for example refs/gitk/failed-rebase and then abort the rebase together with displaying the error message explaining what happened. The edited commit would remain visible and a user can manually cherry pick remaining commits and then reset the original branch to this failed-rebase ref.

Show 7 quoted lines
> I usually do this by starting a new branch just before the commit I
> want to change and then use a combination of the cherry-pick menu item
> and git commit --amend.  Maybe something to make that simpler for
> users would be good, i.e. automate it a bit but still have it be a
> step-by-step process if necessary.  Part of the problem of course is
> that neither gitk nor git gui are really designed to be an editing
> environment.
So what about the following:
1) When user selects "Edit commit", git rebase -i is called, git citool
   is started on background and things will be set up (I do not know yet
   how exactly) so that same callback is called when git citool exits.
2) gitk updates the list of commits and marks the current (detached)
   head by a tag (colored box) saying that there is rebase in progress.
   The same tag would appear if gitk is executed manually during
   interactive rebase.
3) When git citool exits (or when you explicitly select something from
   rebase tag's context menu), rebase would continue.
> In fact you really want an edit/compile/test environment so you don't
> introduce new bugs.

Another possibility would be to allow only editing of the commit message. Then you don't need compile/test steps and the rebase should not fail due to conflicts.

I do not think I would like this limitation, but it would certainly be better then nothing.

-Michal
Jeff King· Aug 25, 2011, 03:07 UTC · re: Michal Sojka · lore

Re: [PATCH RFC] gitk: Allow commit editing

On Fri, Aug 19, 2011 at 02:23:39PM +0200, Michal Sojka wrote:
Show 10 quoted lines
> > Invoking rebase behind the scenes makes me very nervous. In particular:
> > 
> >   1. There is nothing to indicate to the user that they are rewriting a
> >      string of commits, which is going to wreak havoc if any of the
> >      commits have been published elsewhere (either pushed somewhere, or
> >      even present in another local branch). I.e., rebasing generally
> >      needs to be a conscious decision of the user.
> 
> I added a warning if the edited commit is contained in a remote branch.
> Would you consider this sufficient?

It's likely problematic if the commit appears in the history of any other ref, unless they are also planning on rebasing that ref, too (which you can't really know, but it is probably better to warn).

-Peff

← back to recent threads