Rebasing with --collapse would leave the working copy on the parent of the
collapsed commit, instead of on the collapsed commit. This fixes that. Also
fixes a few tests that already covered this area but had bad data.
This also fixes issue3716 where bookmarks are not kept across rebases with
--collapse. I updated the test to cover that case as well.
When aborting a rebase where tip-1 is public, rebase would fail to undo the merge
state. This caused unexpected dirstate parents and also caused unshelve to
become unabortable (since it uses rebase under the hood).
The problem was that rebase uses -2 as a marker rev, and when it checked for
immutableness during the abort, -2 got resolved to the second to last entry in
the phase cache.
Adds a test for the fix. Add exception to phase code to prevent this in the
future.
Prior this changeset, rebasing a merge whose first parent was not in
the rebase lead to wrong and highly conflicting merge. See the in-line
comment for details.
Test have been updated with the data provided by the reported.
Prior to this changeset, rebase always left the working directory as a parent of
the last rebased changeset. The is dubious when, before the rebase, the working
directory was not a parent of the tip most rebased changeset.
With this changeset, we move the working directory back to its original parent.
If the original parent was rebased, we use it's successors.
This is a step toward solving issue3813 (rebase loses active bookmark if it's
not on a head)
This makes it possible to pass keepbranches and extrafn to rebase at
the same time, although nobody uses that functionality presently. This
is a precursor to keeping graft metadata.
Before this patch, "hg summary" may fail, when there is inconsistent
rebase state: for example, the root of rebase destination revisions
recorded in rebase state file is already stripped manually.
Mercurial earlier than 2.7 allows users to do anything other than
starting new rebase, even though current rebase is not finished or
aborted yet. So, such inconsistent rebase states may be left and
forgotten in repositories.
This patch catches RepoLookupError at restoring rebase state for
summary hook, and treat such state as "broken".
Before this patch, "rebase --abort"/"--continue" may fail, when rebase
state is inconsistent: for example, the root of rebase destination
revisions recorded in rebase state file is already stripped manually.
Mercurial earlier than 2.7 allows users to do anything other than
starting new rebase, even though current rebase is not finished or
aborted yet. So, such inconsistent rebase states may be left and
forgotten in repositories.
This patch catches RepoLookupError at restoring rebase state for
abort/continue, and treat such state as "broken".
This saves us a relatively superfluous status check for pull --rebase (if
rebase runs, it'll check for a clean working directory anyway), and brings hg
pull --rebase closer to hg pull && hg rebase.
This is a behavior change because pull --rebase with a dirty working directory
will now abort after performing the pull rather than before.
When a rebase has conflicts and the user uses rebase --continue, the previously
active bookmark was not being made active once again. With this change that
bookmark is made active again, just as if the rebase had never been interrupted.
This changes the rebasestate file format, but should handle old formats correctly.
Since the file is transient, this is even less of a problem.
Adds a test to verify the new behavior. I manually tested continuing rebases
with and without an active bookmark, and with and without being on the bookmark
being rebased.
dest.rev() is the same as target when a new rebase is run, but dest
isn't set when rebase --continue is run. Bug introduced in 97aaac321ced,
which fixed issue3685.
This changeset adds a small mention of it in the help to prevent
confusion. This small addition references online help that is easier to
update and improve at release time.
Following Wagner Bruna's advice, this is added in a plain new paragraph
to not invalidate current translation this close to the release.
Mention that Mercurial helps you not do what you've just been warned not
to do, with a reference to the 'phases' help topic (not the 'phase'
command help).
Thanks to Pierre-Yves David <pierre-yves.david@ens-lyon.org> for
motivating this change and Wagner Bruna
<wagner.bruna+mercurial@gmail.com> for advising on how to do it in an
i18n-friendly way.
With rebase taking multiple roots it is possible to have revision in the "rebase
domain" not rebased themself. We do not want rebased revision above them to be
detached. We want such revision to be rebased on the nearest rebased ancestors.
This allows to preserve the topology of the rebase set as much a possible
To achieve this we introduce a new state `revignored` which informs
`defineparents` of the situation.
The test in `test-rebase-obsolete.t` was actually wrote and his now fixed.
For a proper behavior of the `--rev` revision we will need another possible
state for revision ignored by rebase. We alter the comparison to `nullmerge`
to match this future lower state too.
When rebase results in an empty a changeset it is "skipped" and no related
changeset is created at all. When we added obsolescence support to rebase (in
cee0a253a56c) it seemed a good idea to use its parent successor as the
successors for such dropped changesets. (see old version of the altered test).
This option was chosen because it seems a good way to hint about were the
dropped changeset "intended" to be. Such hint would have been used by automatic
evolution mechanism to rebase potential unstable children.
However, field testing of this version are not conclusive. It very often leads
to the creation of (totally unfounded) evolution divergence. This changeset
changes this behavior and mark skipped changesets as pruned (obsolete without
successors). This prevents the issue and seems semantically better probably a
win for obsolescence reading tool.
See example bellow for details:
User Babar has five changesets of interest:
- O, its current base of development.
- U, the new upstream
- A and C, some development changesets
- B another development changeset independent from A
O - A - B - C
\
U
Babar decides that B is more critical than the A and C and rebase it first
$ hg rebase --rev B --dest U
B is now obsolete (in lower case bellow). Rebase result, B', is its
successors.(note, C is unstable)
O - A - b - C
\
U - B'
Babar is now done with B', and want to rebase the rest of its history:
$ hg rebase --source A --dest B'
hg rebase process A, B and C. B is skipped as all its changes are already contained
in B'.
O - U - B' - A' - C'
Babar have the expected result graph wise, obsolescence marker are as follow:
B -> B' (from first rebase)
A -> A' (from second rebase)
C -> C' (from second rebase)
B -> ?? (from second rebase)
Before this changeset, the last marker is `B -> A'`. This cause two issues:
- This is semantically wrong. B have nothing to do with A'
- B has now two successors sets: (B',) and (A',). We detect a divergent
rewriting. The B' and A' are reported as "divergent" to Babar, confusion
ensues. In addition such divergent situation (divergent changeset are children
to each other) is tricky to solve.
With this changeset the last marker is `B -> ø`:
- This is semantically better.
- B has a single successors set (B',)
This scenario is added to the tests suite.
We have all the necessary mechanism to rebase a set with multiple roots, we only
needed a proper handling of this case we preparing and concluding the rebase.
This changeset des that.
Rebase set with multiple root allows some awesome usage of rebase like:
- rebase all your draft on lastest upstream
hg rebase --dest @ --rev 'draft()'
- exclusion of specific changeset during rebase
hg rebase --rev '42:: - author(Babar)'
- rebase a set of revision were multiple roots are later merged
hg rebase --rev '(18+42)::'
Obsolescence markers can represent this situation just fine. Rebased
revisions are marked as precursors of the ones create by
rebase. Unrebased descendants becomes "unstable".
If obsolescence is not enabled we keep the current behavior of
aborting. This new behavior only applies when obsolete is
enabled and is subject to future discussion and changes.
For a repository with over 400,000 commits, rebasing one revision near tip,
this avoids one walk up the DAG, speeding the operation up by around 0.8
seconds.
Rebase also have a plain `--rev` option used to select the rebase set (as
`--base` or `--source` would). But the content of the --rev option was intended
for the remote repo and is irrelevant for the local rebase operation. We expect
`hg pull --rebase` to stick with the default behavior here:
hg rebase --base . --dest tip(branch(.))
The `rev` option is dropped from the option passed to rebase.
Bookmarks persistence still showed a fair amount of its legacy as a
monkeypatching extension. This encapsulates all bookmarks
serialization and parsing in a single class, and offers a single
location where other bookmarks storage engines can be substituted
in. As a result, many files no longer import the bookmarks module,
which strikes me as an encapsulation win.
This doesn't do anything to the current bookmark state yet, but I'm
hoping put that in the bmstore class as well.
Here, we exclude hidden changesets from a rebase operation. If we
don't, a rewritten version of the hidden changesets will be created
by rebase. Those rewritten versions won't be hidden and will likely
conflict with other rewriting or revive pruned changeset. Moreover,
rewriting hidden revisions will surprise the user.
This change would not be necessary if changelog filtering were
already in core. But it's fairly cheap and helps to increase the
test-suite for such filtering.
Once changelog level filtering is added, hidden changes will be
automatically excluded or included according to the global --hidden
flags. Plain ignoring them is good enough for now.
In collapse mode, that content of state is not suitable to compute obsolescence
markers. We explicitly pass the resulting revision instead and use it as the
successors for all elements of the rebased set.