view tests/test-merge6.t @ 17970:0b03454abae7

ancestor: faster algorithm for difference of ancestor sets One of the major reasons rebase is slow in large repositories is the computation of the detach set: the set of ancestors of the changesets to rebase not in the destination parent. This is currently done via a revset that does two walks all the way to the root of the DAG. Instead of doing that, to find ancestors of a set <revs> not in another set <common> we walk up the tree in reverse revision number order, maintaining sets of nodes visited from <revs>, <common> or both. For the common case where the sets are close both topologically and in revision number (relative to repository size), this has been found to speed up rebase by around 15-20%. When the nodes are farther apart and the DAG is highly branching, it is harder to say which would win. Here's how long computing the detach set takes in a linear repository with over 400000 changesets, rebasing near tip: Rebasing across 4 changesets Revset method: 2.2s New algorithm: 0.00015s Rebasing across 250 changesets Revset method: 2.2s New algorithm: 0.00069s Rebasing across 10000 changesets Revset method: 2.4s New algorithm: 0.019s
author Siddharth Agarwal <sid0@fb.com>
date Mon, 26 Nov 2012 11:46:51 -0800
parents f2719b387380
children 2428e8ec0793
line wrap: on
line source

  $ cat <<EOF > merge
  > import sys, os
  > print "merging for", os.path.basename(sys.argv[1])
  > EOF
  $ HGMERGE="python ../merge"; export HGMERGE

  $ hg init A1
  $ cd A1
  $ echo This is file foo1 > foo
  $ echo This is file bar1 > bar
  $ hg add foo bar
  $ hg commit -m "commit text"

  $ cd ..
  $ hg clone A1 B1
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved

  $ cd A1
  $ rm bar
  $ hg remove bar
  $ hg commit -m "commit test"

  $ cd ../B1
  $ echo This is file foo22 > foo
  $ hg commit -m "commit test"

  $ cd ..
  $ hg clone A1 A2
  updating to branch default
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg clone B1 B2
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved

  $ cd A1
  $ hg pull ../B1
  pulling from ../B1
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files (+1 heads)
  (run 'hg heads' to see heads, 'hg merge' to merge)
  $ hg merge
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  (branch merge, don't forget to commit)
  $ hg commit -m "commit test"
bar should remain deleted.
  $ hg manifest --debug
  f9b0e817f6a48de3564c6b2957687c5e7297c5a0 644   foo

  $ cd ../B2
  $ hg pull ../A2
  pulling from ../A2
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 0 changes to 0 files (+1 heads)
  (run 'hg heads' to see heads, 'hg merge' to merge)
  $ hg merge
  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
  (branch merge, don't forget to commit)
  $ hg commit -m "commit test"
bar should remain deleted.
  $ hg manifest --debug
  f9b0e817f6a48de3564c6b2957687c5e7297c5a0 644   foo

  $ cd ..