When the `--fork-point` argument was added to `git rebase`, we changed
the value of $upstream to be the fork point instead of the point from
which we want to rebase. When $orig_head..$upstream is empty this does
not change the behaviour, but when there are new changes in the upstream
we are no longer checking if any of them are patch-identical with
changes in $upstream..$orig_head.
Fix this by introducing a new variable to hold the fork point and using
this to restrict the range as an extra (negative) revision argument so
that the set of desired revisions becomes (in fork-point mode):
git rev-list --cherry-pick --right-only \
$upstream...$orig_head ^$fork_point
This allows us to correctly handle the scenario where we have the
following topology:
C --- D --- E <- dev
/
B <- master@{1}
/
o --- B' --- C* --- D* <- master
where:
- B' is a fixed-up version of B that is not patch-identical with B;
- C* and D* are patch-identical to C and D respectively and conflict
textually if applied in the wrong order;
- E depends textually on D.
The correct result of `git rebase master dev` is that B is identified as
the fork-point of dev and master, so that C, D, E are the commits that
need to be replayed onto master; but C and D are patch-identical with C*
and D* and so can be dropped, so that the end result is:
o --- B' --- C* --- D* --- E <- dev
If the fork-point is not identified, then picking B onto a branch
containing B' results in a conflict and if the patch-identical commits
are not correctly identified then picking C onto a branch containing D
(or equivalently D*) results in a conflict.
This change allows us to handle both of these cases, where previously we
either identified the fork-point (with `--fork-point`) but not the
patch-identical commits *or* (with `--no-fork-point`) identified the
patch-identical commits but not the fact that master had been rewritten.
Reported-by: Ted Felix <ted@tedfelix.com>
Signed-off-by: John Keeping <john@keeping.me.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The construct is error-prone; "test" being built-in in most modern
shells, the reason to avoid "test <cond> && test <cond>" spawning
one extra process by using a single "test <cond> -a <cond>" no
longer exists.
Signed-off-by: Elia Pinto <gitter.spiros@gmail.com>
Reviewed-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When a user invokes
$ git rebase -i @~3
with dirty files and rebase.autostash turned on, and exits the $EDITOR
with an empty buffer, the autostash fails to apply. Although the primary
focus of rr/rebase-autostash was to get the git-rebase--backend.sh
scripts to return control to git-rebase.sh, it missed this case in
git-rebase--interactive.sh. Since this case is unlike the other cases
which return control for housekeeping, assign it a special return status
and handle that return value explicitly in git-rebase.sh.
Reported-by: Karen Etheridge <ether@cpan.org>
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Work around /bin/sh that does not like "return" at the top-level
of a file that is dot-sourced from inside a function definition.
* km/avoid-non-function-return-in-rebase:
Revert "rebase: fix run_specific_rebase's use of "return" on FreeBSD"
rebase: avoid non-function use of "return" on FreeBSD
Since a1549e10, 15d4bf2e and 01a1e646 (first appearing in v1.8.4)
the git-rebase--*.sh scripts have used a "return" to stop execution
of the dot-sourced file and return to the "dot" command that
dot-sourced it. The /bin/sh utility on FreeBSD however behaves
poorly under some circumstances when such a "return" is executed.
In particular, if the "dot" command is contained within a function,
then when a "return" is executed by the script it runs (that is not
itself inside a function), control will return from the function
that contains the "dot" command skipping any statements that might
follow the dot command inside that function. Commit 99855ddf (first
appearing in v1.8.4.1) addresses this by making the "dot" command
the last line in the function.
Unfortunately the FreeBSD /bin/sh may also execute some statements
in the script run by the "dot" command that appear after the
troublesome "return". The fix in 99855ddf does not address this
problem.
For example, if you have script1.sh with these contents:
run_script2() {
. "$(dirname -- "$0")/script2.sh"
_e=$?
echo only this line should show
[ $_e -eq 5 ] || echo expected status 5 got $_e
return 3
}
run_script2
e=$?
[ $e -eq 3 ] || { echo expected status 3 got $e; exit 1; }
And script2.sh with these contents:
if [ 5 -gt 3 ]; then
return 5
fi
case bad in *)
echo always shows
esac
echo should not get here
! :
When running script1.sh (e.g. '/bin/sh script1.sh' or './script1.sh'
after making it executable), the expected output from a POSIX shell
is simply the single line:
only this line should show
However, when run using FreeBSD's /bin/sh, the following output
appears instead:
should not get here
expected status 3 got 1
Not only did the lines following the "dot" command in the run_script2
function in script1.sh get skipped, but additional lines in script2.sh
following the "return" got executed -- but not all of them (e.g. the
"echo always shows" line did not run).
These issues can be avoided by not using a top-level "return" in
script2.sh. If script2.sh is changed to this:
main() {
if [ 5 -gt 3 ]; then
return 5
fi
case bad in *)
echo always shows
esac
echo should not get here
! :
}
main
Then it behaves the same when using FreeBSD's /bin/sh as when using
other more POSIX compliant /bin/sh implementations.
We fix the git-rebase--*.sh scripts in a similar fashion by moving
the top-level code that contains "return" statements into its own
function and then calling that as the last line in the script.
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
Acked-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In some places we "echo" a string that comes from a commit log
message, which may have a backslash sequence that is interpreted by
the command (POSIX.1 allows this), most notably "dash"'s built-in
'echo'.
A commit message which contains the string '\n' (or ends with the
string '\c') may result in a garbage line in the todo list of an
interactive rebase which causes the rebase to fail.
To reproduce the behavior (with dash as /bin/sh):
mkdir test && cd test && git init
echo 1 >foo && git add foo
git commit -m"this commit message ends with '\n'"
echo 2 >foo && git commit -a --fixup HEAD
git rebase -i --autosquash --root
Now the editor opens with garbage in line 3 which has to be
removed or the rebase fails.
Signed-off-by: Uwe Storbeck <uwe@ibr.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Nicolas Vigier <boklm@mars-attacks.org>
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In a shell snippet meant to be sourced by other shell scripts, an
opening #! line does more harm than good.
The harm:
- When the shell library is sourced, the interpreter and options from
the #! line are not used. Specifying a particular shell can
confuse the reader into thinking it is safe for the shell library
to rely on idiosyncrasies of that shell.
- Using #! instead of a plain comment drops a helpful visual clue
that this is a shell library and not a self-contained script.
- Tools such as lintian can use a #! line to tell when an
installation script has failed by forgetting to set a script
executable. This check does not work if shell libraries also start
with a #! line.
The good:
- Text editors notice the #! line and use it for syntax highlighting
if you try to edit the installed scripts (without ".sh" suffix) in
place.
The use of the #! for file type detection is not needed because Git's
shell libraries are meant to be edited in source form (with ".sh"
suffix). Replace the opening #! lines with comments.
This involves tweaking the test harness's valgrind support to find
shell libraries by looking for "# " in the first line instead of "#!"
(see v1.7.6-rc3~7, 2011-06-17).
Suggested by Russ Allbery through lintian. Thanks to Jeff King and
Clemens Buchacher for further analysis.
Tested by searching for non-executable scripts with #! line:
find . -name .git -prune -o -type f -not -executable |
while read file
do
read line <"$file"
case $line in
'#!'*)
echo "$file"
;;
esac
done
The only remaining scripts found are templates for shell scripts
(unimplemented.sh, wrap-for-bin.sh) and sample input used in tests
(t/t4034/perl/{pre,post}).
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
collapse_todo_ids() uses `git rev-parse --short=7' to abbreviate
commit ids before showing them to the user in a text editor. Let's
drop argument from --short to the configured value instead (still
defaulting to 7).
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
The commit object names in the insn sheet that was prepared at the
beginning of "rebase -i" session can become ambiguous as the
rebasing progresses and the repository gains more commits. Make
sure the internal record is kept with full 40-hex object names.
* es/rebase-i-no-abbrev:
rebase -i: fix short SHA-1 collision
t3404: rebase -i: demonstrate short SHA-1 collision
t3404: make tests more self-contained
"git rebase -p" internally used the merge machinery, but when
rebasing, there should not be a need for merge summary.
* rt/rebase-p-no-merge-summary:
rebase --preserve-merges: ignore "merge.log" config
"rebase -i" forgot that the comment character can be configurable
while reading its insn sheet.
* es/rebase-i-respect-core-commentchar:
rebase -i: fix cases ignoring core.commentchar
The 'todo' sheet for interactive rebase shows abbreviated SHA-1's and
then performs its operations upon those shortened values. This can lead
to an abort if the SHA-1 of a reworded or edited commit is no longer
unique within the abbreviated SHA-1 space and a subsequent SHA-1 in the
todo list has the same abbreviated value.
For example:
edit f00dfad first
pick badbeef second
If, after editing, the new SHA-1 of "first" also has prefix badbeef,
then the subsequent 'pick badbeef second' will fail since badbeef is no
longer a unique SHA-1 abbreviation:
error: short SHA1 badbeef is ambiguous.
fatal: Needed a single revision
Invalid commit name: badbeef
Fix this problem by expanding the SHA-1's in the todo list before
performing the operations.
[es: also collapse & expand SHA-1's for --edit-todo; respect
core.commentchar in transform_todo_ids(); compose commit message]
Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When "merge.log" config is set, "rebase --preserve-merges" will add
the log lines to the message of the rebased merge commit. A rebase
should not modify a commit message automatically.
Teach "git-rebase" to ignore that configuration by passing
"--no-log" to the git-merge call.
Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
180bad3d (rebase -i: respect core.commentchar, 2013-02-11) updated
"rebase -i" to honor core.commentchar but missed one instance of
hard-coded '#' comment character in skip_unnecessary_picks().
Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
"git rebase [-i]" used to leave just "rebase" as its reflog message
for some operations. This rewords them to be more informative.
* rr/rebase-reflog-message-reword:
rebase -i: use a better reflog message
rebase: use a better reflog message
Merge strategy and its options can be specified in `git rebase`,
but with `--interactive`, they were completely ignored.
Signed-off-by: Arnaud Fontaine <arnau@debian.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In rebase -i --autosquash, ignore all "fixup! " or "squash! " after the
first. This supports the case when a git commit --fixup/--squash referred
to an earlier fixup/squash instead of the original commit (whether
intentionally, as when the user expressly meant to note that the commit
fixes an earlier fixup; or inadvertently, as when the user meant to refer to
the original commit with :/msg; or out of laziness, as when the user could
remember how to refer to the fixup but not the original).
In the todo list, the full commit message is preserved, in case it provides
useful cues to the user. A test helper set_cat_todo_editor is introduced to
check this.
Helped-by: Thomas Rast <trast@inf.ethz.ch>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Andrew Pimlott <andrew@pimlott.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Now that the "checkout" invoked internally from "rebase -i" knows to
honor GIT_REFLOG_ACTION, we can start to use it to write a better
reflog message when "rebase anotherbranch", "rebase --onto branch",
etc. internally checks out the new fork point. We will write:
rebase -i: checkout master
instead of the old
rebase -i
As all the calls git-rebase--interactive make to underlying git
commands that leave reflog messages are preceded by the internal
comment_for_reflog helper function, which uses the original value of
the GIT_REFLOG_ACTION variable it saw when it first started, the new
assignments to GIT_REFLOG_ACTION actively contaminate the value of
the variable, knowing that it will be reset to a sane value before
it is used again. This does not generally hold true but it should
suffice for now.
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Return control to the caller git-rebase.sh to get these two tasks
rm -fr "$dotest"
git gc --auto
done by it.
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
In preparation for a later patch that will create $state_dir/autostash
in git-rebase.sh before anything else can happen, change a `mkdir
$state_dir` call to `mkdir -p $state_dir`. The change is safe,
because this is not a test to detect an in-progress rebase (that is
already done much earlier in git-rebase.sh).
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When a rebase stops (e.g. interrupted by a merge conflict), it could
be useful to know how far a rebase has progressed and how many
commits in total this rebase will apply. Teach the __git_ps1()
command to display the number of commits so far applied and the
total number of commits to be applied, like this:
((3ec0a6a...)|REBASE 2/5)
In the example above the rebase has stopped at the second commit due to
a merge conflict and there are a total number of five commits to be
applied by this rebase.
This information can be already obtained from the following files which are
being generated during the rebase:
GIT_DIR/.git/rebase-merge/msgnum (git-rebase--merge.sh)
GIT_DIR/.git/rebase-merge/end (git-rebase--merge.sh)
GIT_DIR/.git/rebase-apply/next (git-am.sh)
GIT_DIR/.git/rebase-apply/last (git-am.sh)
but "rebase -i" does not leave necessary clues.
Implement this feature by doing these three things:
1) Modify git-rebase--interactive.sh to also create
GIT_DIR/.git/rebase-merge/msgnum
GIT_DIR/.git/rebase-merge/end
files for the number of commits so far applied and the total
number of commits to be applied.
2) Modify git-prompt.sh to read and display info from the above
files.
3) Update test t9903-bash-prompt.sh to reflect changes introduced
by this patch.
Signed-off-by: Zoltan Klinger <zoltan.klinger@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Commit eff80a9 (Allow custom "comment char") introduced a custom comment
character for commit messages but did not teach git-rebase--interactive
to use it.
Change git-rebase--interactive to read core.commentchar and use its
value when generating commit messages and for the command list.
Signed-off-by: John Keeping <john@keeping.me.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
An earlier change to add --keep-empty option broke "git rebase
--preserve-merges" and lost merge commits that end up being the
same as its parent.
* ph/rebase-preserve-all-merges:
rebase --preserve-merges: keep all merge commits including empty ones
Since 90e1818f9a (git-rebase: add keep_empty flag, 2012-04-20)
'git rebase --preserve-merges' fails to preserve empty merge commits
unless --keep-empty is also specified. Merge commits should be
preserved in order to preserve the structure of the rebased graph,
even if the merge commit does not introduce changes to the parent.
Teach rebase not to drop merge commits only because they are empty.
A special case which is not handled by this change is for a merge commit
whose parents are now the same commit because all the previous different
parents have been dropped as a result of this rebase or some previous
operation.
Signed-off-by: Phil Hord <hordp@cisco.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Teach an option to edit the insn sheet to "git rebase -i".
* aw/rebase-i-edit-todo:
rebase -i: suggest using --edit-todo to fix an unknown instruction
rebase -i: Add tests for "--edit-todo"
rebase -i: Teach "--edit-todo" action
rebase -i: Refactor help messages for todo file
rebase usage: subcommands can not be combined with -i
We have now an explicit UI to edit the todo sheet and need not disclose
the name of the file.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When the todo sheet of interactive rebase instructs to run a non-existing
command, the operation stops with the following error:
Execution failed: no-such
You can fix the problem, and then run
git rebase --continue
fatal: 'rebase' appears to be a git command, but we were not
able to execute it. Maybe git-rebase is broken?
The reason is that the shell that attempted to run the command exits with
code 127. rebase--interactive just forwards this code to the caller (the
git wrapper). But our smart run-command infrastructure detects this
special exit code and turns it into ENOENT, which in turn is interpreted
by the git wrapper as if the external command that it just executed did
not exist. This is finally translated to the misleading last two lines in
error message cited above.
Fix it by translating the error code before it is forwarded.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This allows users to edit the todo file while they're stopped in the
middle of an interactive rebase. When this action is executed, all
comments from the original todo file are stripped, and new help messages
are appended to the end.
Signed-off-by: Andrew Wong <andrew.kw.w@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
* maint-1.7.11:
Almost 1.7.11.6
gitweb: URL-decode $my_url/$my_uri when stripping PATH_INFO
rebase -i: use full onto sha1 in reflog
sh-setup: protect from exported IFS
receive-pack: do not leak output from auto-gc to standard output
t/t5400: demonstrate breakage caused by informational message from prune
setup: clarify error messages for file/revisions ambiguity
send-email: improve RFC2047 quote parsing
fsck: detect null sha1 in tree entries
do not write null sha1s to on-disk index
diff: do not use null sha1 as a sentinel value
The reflog entries left by "git rebase" and "git rebase -i" were
inconsistent (the interactive one gave an abbreviated object name).
* mg/rebase-i-onto-reflog-in-full:
rebase -i: use full onto sha1 in reflog
The reflog entries left by "git rebase" and "git rebase -i" were
inconsistent.
* mg/rebase-i-onto-reflog-in-full:
rebase -i: use full onto sha1 in reflog
'git rebase' uses the full onto sha1 for the reflog message whereas 'git
rebase -i' uses the short sha1. This is not only inconsistent, but can
lead to problems when the reflog is inspected at a later time at which
that abbreviation may have become ambiguous.
Make 'rebase -i' use the full onto sha1, as well.
Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
There is a bug with git rebase -i --root when a fixup or squash line is
applied to the new root. We attempt to amend the commit onto which they
apply with git reset --soft HEAD^ followed by a normal commit. Unlike a
real commit --amend, this sequence will fail against a root commit as it
has no parent.
Fix rebase -i to use commit --amend for fixup and squash instead, and
add a test for the case of a fixup of the root commit.
Signed-off-by: Chris Webb <chris@arachsys.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
"git rebase [-i] --root $tip" can now be used to rewrite all the
history down to the root.
* cw/rebase-i-root:
t3404: make test 57 work with dash and others
Add tests for rebase -i --root without --onto
rebase -i: support --root without --onto
Teach "am --rebasing" codepath to grab authorship, log message and
the patch text directly out of existing commits. This will help
rebasing commits that have confusing "diff" output in their log
messages.
* mz/rebase-no-mbox:
am: don't call mailinfo if $rebasing
am --rebasing: get patch body from commit, not from mailbox
rebase --root: print usage on too many args
rebase: don't source git-sh-setup twice
Allow --root to be specified to rebase -i without --onto, making it
possible to edit and re-order all commits right back to the root(s).
If there is a conflict to be resolved when applying the first change,
the user will expect a sane index and working tree to get sensible
behaviour from git-diff and friends, so create a sentinel commit with an
empty tree to rebase onto. Automatically squash the sentinel with any
commits rebased directly onto it, so they end up as root commits in
their own right and retain their authorship and commit message.
Implicitly use rebase -i for non-interactive rebase of --root without
an --onto argument now that rebase -i can correctly do this.
Signed-off-by: Chris Webb <chris@arachsys.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The git-sh-setup script is already sourced in git-rebase.sh before
calling into git-rebase--(am|interactive|merge).sh. There are no other
callers of these scripts. It is therefore unnecessary to source
git-sh-setup again in them.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
During an interactive rebase session, it is sometimes desirable to
run tests on each commit in the resulting history. This can be done
by adding "exec <test command>" when editing the insn sheet, but the
command used for testing is often the same for all resulting commits.
By passing "--exec <cmd>" from the command line, automatically add
these "exec" lines after each commit in the final history. To work
well with the --autosquash option, these are added at the end of
each run of "fixup" and "squash".
Helped-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>
Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>
Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>
Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>
Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
"git rebase" learned to optionally keep commits that do not introduce
any change in the original history.
By Neil Horman
* nh/empty-rebase:
git-rebase: add keep_empty flag
git-cherry-pick: Add test to validate new options
git-cherry-pick: Add keep-redundant-commits option
git-cherry-pick: add allow-empty option
Add a command line switch to git-rebase to allow a user the ability to specify
that they want to keep any commits in a series that are empty.
When git-rebase's type is am, then this option will automatically keep any
commit that has a tree object identical to its parent.
This patch changes the default behavior of interactive rebases as well. With
this patch, git-rebase -i will produce a revision set passed to
git-revision-editor, in which empty commits are commented out. Empty commits
may be kept manually by uncommenting them. If the new --keep-empty option is
used in an interactive rebase the empty commits will automatically all be
uncommented in the editor.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Giving "--continue" to a conflicted "rebase -i" session skipped a commit
that only results in changes to submodules.
By John Keeping
* jk/rebase-i-submodule-conflict-only:
rebase -i continue: don't skip commits that only change submodules