Bug 513726 - Interactive Rebase fails on fixup if target contains hash in commit message
Summary: Interactive Rebase fails on fixup if target contains hash in commit message
Status: RESOLVED FIXED
Alias: None
Product: JGit
Classification: Technology
Component: JGit (show other bugs)
Version: 4.2   Edit
Hardware: All All
: P3 minor (vote)
Target Milestone: 6.1   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-03-15 15:02 EDT by Stefan Mandel CLA
Modified: 2022-02-02 17:06 EST (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stefan Mandel CLA 2017-03-15 15:02:06 EDT
When I want to rebase interactivly having a commit:
- #9 documentation
- commit to fixup

Leads to an error popup, containing the details:

An internal error occurred during: "Processing Steps".
String index out of range: -1

The stacktrace found in the logs is:

!ENTRY org.eclipse.egit.ui 1 0 2017-03-15 07:24:45.700
!MESSAGE Result status: INTERACTIVE_PREPARED

!ENTRY org.eclipse.core.jobs 4 2 2017-03-15 07:24:54.248
!MESSAGE An internal error occurred during: "Processing Steps".
!STACK 0
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
	at java.lang.AbstractStringBuilder.deleteCharAt(AbstractStringBuilder.java:824)
	at java.lang.StringBuilder.deleteCharAt(StringBuilder.java:253)
	at org.eclipse.jgit.api.RebaseCommand.stripCommentLines(RebaseCommand.java:806)
	at org.eclipse.jgit.api.RebaseCommand.squashIntoPrevious(RebaseCommand.java:785)
	at org.eclipse.jgit.api.RebaseCommand.doSquashFixup(RebaseCommand.java:746)
	at org.eclipse.jgit.api.RebaseCommand.processStep(RebaseCommand.java:486)
	at org.eclipse.jgit.api.RebaseCommand.call(RebaseCommand.java:368)
	at org.eclipse.egit.core.op.RebaseOperation$1.run(RebaseOperation.java:155)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2240)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2267)
	at org.eclipse.egit.core.op.RebaseOperation.execute(RebaseOperation.java:175)
	at org.eclipse.egit.core.internal.job.JobUtil$2.runInWorkspace(JobUtil.java:105)
	at org.eclipse.core.internal.resources.InternalWorkspaceJob.run(InternalWorkspaceJob.java:39)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
Comment 1 Stefan Mandel CLA 2017-03-15 15:05:25 EDT
For clarification:

- there are two commits
- one commit should fixup the former
- the former commit message contains a '#' (hash), yet I only tried it at the first position of the commit message

Trying to perform this rebase fails, with the error message in the previous comment.
Comment 2 Stefan Mandel CLA 2017-03-15 15:19:20 EDT
Another hint that the # is a problem in commit messages:

I tried to squash both commits (instead of using fixup) and left the message "#9 documentation". The squashed commit message did not contain this string but was empty and had to be reworded (Reword with the message "#9 documentation" works).
Comment 3 Eclipse Genie CLA 2017-03-15 15:29:42 EDT
New Gerrit change created: https://git.eclipse.org/r/93154
Comment 4 Eclipse Genie CLA 2017-03-15 19:19:34 EDT
Gerrit change https://git.eclipse.org/r/93154 was merged to [master].
Commit: http://git.eclipse.org/c/jgit/jgit.git/commit/?id=a4b9c73391d75b6069908ce67e4414f30105c947
Comment 5 Stefan Mandel CLA 2017-09-08 05:33:30 EDT
I just tested it with eclipse neon2 and oxygen. Fixup and Squash delete the commit message if a hash (#) is contained:

To reproduce (fixup):
- create two commits with comments '#first' and '#second'
- interactive rebase
- mark #second to fixup #first
- the resulting (merged) commit has not commit message

To reproduce (squash):
- create two commits with comments '#first' and '#second'
- interactive rebase
- mark #second to squash #first
- choose a new comment '#third'
- the resulting (merged) commit has not commit message
Comment 6 Thomas Wolf CLA 2017-09-08 08:54:22 EDT
(In reply to Stefan Mandel from comment #5)
> I just tested it with eclipse neon2 and oxygen. Fixup and Squash delete the
> commit message if a hash (#) is contained:
> 
> To reproduce (fixup):
> - create two commits with comments '#first' and '#second'
> - interactive rebase
> - mark #second to fixup #first
> - the resulting (merged) commit has not commit message
> 
> To reproduce (squash):
> - create two commits with comments '#first' and '#second'
> - interactive rebase
> - mark #second to squash #first
> - choose a new comment '#third'
> - the resulting (merged) commit has not commit message

For squash, this is to be expected. Lines starting with # are removed. Fixup, however, should not touch the commit message but just take whatever the first commit's message is, without further comment stripping.

The C implementation of git also treats lines starting with # in commit messages as comments and strips them when you edit the commit message interactively.

That said, I would say having commit messages with '#'-signs at the beginning of lines (even if created via git commit -m '#foo') should simply be avoided. It'll lead to surprising effects with normal git, too.

Note that git has a core.commentChar config that defines this comment character; '#' is just the default value. JGit/EGit does not implement this setting yet.
Comment 7 Thomas Wolf CLA 2022-01-17 10:55:09 EST
The bug from comment 0 was fixed in [1].

The squash case is now bug 578173.

The fixup case is still present in JGit 6.1. Seems to be a bug in RebaseCommand.  

[1] https://git.eclipse.org/r/c/jgit/jgit/+/93154/
Comment 8 Thomas Wolf CLA 2022-01-17 18:16:44 EST
(In reply to Thomas Wolf from comment #7)
> The fixup case is still present in JGit 6.1. Seems to be a bug in
> RebaseCommand.  

The bug is in the handling of the MESSAGE_FIXUP file inside RebaseCommand.

C git says[1]

  If the current series of squash/fixups has not yet included a squash
  command, then this file exists and holds the commit message of the
  original "pick" commit.  (If the series ends without a "squash"
  command, then this can be used as the commit message of the combined
  commit without opening the editor.)

So it should be the original commit message of the commit being amended, verbatim.

But JGit accumulates messages in this file, with comment lines, and at the end (on the last fixup) strips out comment lines. That of course also strips out any line in the original commit that happened to start with a hash.

[1] https://github.com/git/git/blob/df3c41adeb/sequencer.c#L86 ff.
Comment 9 Eclipse Genie CLA 2022-01-18 03:42:58 EST
New Gerrit change created: https://git.eclipse.org/r/c/jgit/jgit/+/189728