view tests/test-sharing.t @ 3846:f9dad99a90d5

evolve: create a new commit instead of amending one of the divergents This patch changes the behavior of evolve command while resolving content-divergence to create a new commit instead of amending one of the divergent ones. In past, I have made this change, backed out this change and now today again I am doing this change, so let's dive in some history. Using cmdrewrite.amend() was never a good option as that requires hack to delete the evolvestate and also gives us less control over things. We can't make the commit on top of different parents as that of content-divergent ones. Due to all these, I first made this change to create a new commit instead of amending one. But, after few days, there was flakiness observed in the tests and turned out that we need to do some dirstate dance as repo.dirstate.setparents() does not always fix the dirstate. That flakiness was a blocker for progress at that time and we decided to switch to amend back so that we can have things working with some hacks and we can later fix the implementation part. Now, yesterday while tackling resolving content-divergence of a stack which is as follows: C1 C2 | | B1 B2 | | A1 A2 \/ base where, A1-A2, B1-B2, C1-C2 are content-divergent with each other. Now we can resolve A1-A2 very well because they have the same parent and let's say that resolution leads to A3. Now, we want to resolve B1-B2 and make the new resolution commit on top of A3 so that we can end up something like: C3 | B3 | A3 | base however, amending one of the divergent changesets, it's not possible to create a commit on a different parent like A3 here without some relocation. We should prevent relocation as that may leads to some conflicts and should change the parent before committing. So, looking ahead, we can't move with using amend as still using that we will need some relocation hacks making code ugly and prone to bad behaviors, bugs. Let's change back to creating a new commit so that we can move forward in a good way. About repo.dirstate.setparents() not setting the dirstate, I have researched yesterday night about how we can do that and found out that we can use cmdrewrite._uncommitdirstate() here. Expect upcoming patches to improve the documentation of that function. There are lot of test changes because of change in hash but there is no behavior change. The only behavior change is in test-evolve-abort-contentdiv.t which is nice because creating a new commit helps us in stripping that while aborting. We have a lot of testing of content-divergence and no behavior change gives enough confidence for making this change. I reviewed the patch carefully to make sure there is no behavior change and I suggest reviewer to do the same.
author Pulkit Goyal <7895pulkit@gmail.com>
date Wed, 13 Jun 2018 17:15:10 +0530
parents 4bad80f1aad3
children d00f0c369bc7 ef22eef37ecc
line wrap: on
line source

Test script based on sharing.rst: ensure that all scenarios in that
document work as advertised.

Setting things up

  $ cat >> $HGRCPATH <<EOF
  > [alias]
  > shortlog = log --template '{rev}:{node|short}  {phase}  {desc|firstline}\n'
  > [extensions]
  > rebase =
  > EOF
  $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
  $ hg init public
  $ hg clone public test-repo
  updating to branch default
  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg clone test-repo dev-repo
  updating to branch default
  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ cat >> test-repo/.hg/hgrc <<EOF
  > [phases]
  > publish = false
  > EOF

To start things off, let's make one public, immutable changeset::

  $ cd test-repo
  $ echo 'my new project' > file1
  $ hg add file1
  $ hg commit -m'create new project'
  $ hg push
  pushing to $TESTTMP/public (glob)
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files

and pull that into the development repository::

  $ cd ../dev-repo
  $ hg pull -u
  pulling from $TESTTMP/test-repo (glob)
  requesting all changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files
  new changesets 0dc9c9f6ab91
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved

Let's commit a preliminary change and push it to ``test-repo`` for
testing. ::

  $ echo 'fix fix fix' > file1
  $ hg commit -m'prelim change'
  $ hg push -q ../test-repo

Figure SG01 (roughly)
  $ hg shortlog -G
  @  1:f6490818a721  draft  prelim change
  |
  o  0:0dc9c9f6ab91  public  create new project
  
Now let's switch to test-repo to test our change and amend::
  $ cd ../test-repo
  $ hg update -q
  $ echo 'Fix fix fix.' > file1
  $ hg amend -m'fix bug 37'

Figure SG02
  $ hg shortlog --hidden -G
  @  2:60ffde5765c5  draft  fix bug 37
  |
  | x  1:f6490818a721  draft  prelim change
  |/
  o  0:0dc9c9f6ab91  public  create new project
  
Pull into dev-repo: obsolescence markers are transferred, but not
the new obsolete changeset.
  $ cd ../dev-repo
  $ hg pull -u
  pulling from $TESTTMP/test-repo (glob)
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files (+1 heads)
  1 new obsolescence markers
  obsoleted 1 changesets
  new changesets 60ffde5765c5
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  updated to "60ffde5765c5: fix bug 37"
  1 other heads for branch "default"

Figure SG03
  $ hg shortlog --hidden -G
  @  2:60ffde5765c5  draft  fix bug 37
  |
  | x  1:f6490818a721  draft  prelim change
  |/
  o  0:0dc9c9f6ab91  public  create new project
  
Amend again in dev-repo
  $ echo 'Fix, fix, and fix.' > file1
  $ hg amend
  $ hg push -q

Figure SG04 (dev-repo)
  $ hg shortlog --hidden -G
  @  3:de6151c48e1c  draft  fix bug 37
  |
  | x  2:60ffde5765c5  draft  fix bug 37
  |/
  | x  1:f6490818a721  draft  prelim change
  |/
  o  0:0dc9c9f6ab91  public  create new project
  
Figure SG04 (test-repo)
  $ cd ../test-repo
  $ hg update
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  updated to "de6151c48e1c: fix bug 37"
  1 other heads for branch "default"
  $ hg shortlog --hidden -G
  @  3:de6151c48e1c  draft  fix bug 37
  |
  | x  2:60ffde5765c5  draft  fix bug 37
  |/
  | x  1:f6490818a721  draft  prelim change
  |/
  o  0:0dc9c9f6ab91  public  create new project
  
This bug fix is finished. We can push it to the public repository.
  $ hg push
  pushing to $TESTTMP/public (glob)
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files
  2 new obsolescence markers

Now that the fix is public, we cannot amend it any more.
  $ hg amend -m 'fix bug 37'
  abort: cannot amend public changesets: de6151c48e1c
  (see 'hg help phases' for details)
  [255]

Figure SG05
  $ hg -R ../public shortlog -G
  o  1:de6151c48e1c  public  fix bug 37
  |
  o  0:0dc9c9f6ab91  public  create new project
  
Oops, still have draft changesets in dev-repo: push the phase change there.
  $ hg -R ../dev-repo shortlog -r 'draft()'
  3:de6151c48e1c  draft  fix bug 37
  $ hg push ../dev-repo
  pushing to ../dev-repo
  searching for changes
  no changes found
  [1]
  $ hg -R ../dev-repo shortlog -r 'draft()'

Sharing with multiple developers: code review

  $ cd ..
  $ hg clone public review
  updating to branch default
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg clone review alice
  updating to branch default
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg clone review bob
  updating to branch default
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ cat >> review/.hg/hgrc <<EOF
  > [phases]
  > publish = false
  > EOF

Alice commits a draft bug fix, pushes to review repo.
  $ cd alice
  $ hg bookmark bug15
  $ echo 'fix' > file2
  $ hg commit -A -u alice -m 'fix bug 15 (v1)'
  adding file2
  $ hg push -B bug15
  pushing to $TESTTMP/review (glob)
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files
  exporting bookmark bug15
  $ hg -R ../review bookmarks
     bug15                     2:f91e97234c2b

Alice receives code review, amends her fix, and goes out to lunch to
await second review.
  $ echo 'Fix.' > file2
  $ hg amend -m 'fix bug 15 (v2)'
  $ hg push
  pushing to $TESTTMP/review (glob)
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files (+1 heads)
  1 new obsolescence markers
  obsoleted 1 changesets
  updating bookmark bug15
  $ hg -R ../review bookmarks
     bug15                     3:cbdfbd5a5db2

Figure SG06: review repository after Alice pushes her amended changeset.
  $ hg --hidden -R ../review shortlog -G -r 1::
  o  3:cbdfbd5a5db2  draft  fix bug 15 (v2)
  |
  | x  2:f91e97234c2b  draft  fix bug 15 (v1)
  |/
  @  1:de6151c48e1c  public  fix bug 37
  |
  ~

Bob commits a draft changeset, pushes to review repo.
  $ cd ../bob
  $ echo 'stuff' > file1
  $ hg bookmark featureX
  $ hg commit -u bob -m 'implement feature X (v1)'
  $ hg push -B featureX
  pushing to $TESTTMP/review (glob)
  searching for changes
  remote has heads on branch 'default' that are not known locally: cbdfbd5a5db2
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files (+1 heads)
  exporting bookmark featureX
  $ hg -R ../review bookmarks
     bug15                     3:cbdfbd5a5db2
     featureX                  4:193657d1e852

Bob receives first review, amends and pushes.
  $ echo 'do stuff' > file1
  $ hg amend -m 'implement feature X (v2)'
  $ hg push
  pushing to $TESTTMP/review (glob)
  searching for changes
  remote has heads on branch 'default' that are not known locally: cbdfbd5a5db2
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files (+1 heads)
  1 new obsolescence markers
  obsoleted 1 changesets
  updating bookmark featureX

Bob receives second review, amends, and pushes to public:
this time, he's sure he got it right!
  $ echo 'Do stuff.' > file1
  $ hg amend -m 'implement feature X (v3)'
  $ hg push ../public
  pushing to ../public
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files
  2 new obsolescence markers
  $ hg -R ../public bookmarks
  no bookmarks set
  $ hg push ../review
  pushing to ../review
  searching for changes
  remote has heads on branch 'default' that are not known locally: cbdfbd5a5db2
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files (+1 heads)
  1 new obsolescence markers
  obsoleted 1 changesets
  updating bookmark featureX
  $ hg -R ../review bookmarks
     bug15                     3:cbdfbd5a5db2
     featureX                  6:540ba8f317e6

Figure SG07: review and public repos after Bob implements feature X.
  $ hg --hidden -R ../review shortlog -G -r 1::
  o  6:540ba8f317e6  public  implement feature X (v3)
  |
  | x  5:0eb74a7b6698  draft  implement feature X (v2)
  |/
  | x  4:193657d1e852  draft  implement feature X (v1)
  |/
  | o  3:cbdfbd5a5db2  draft  fix bug 15 (v2)
  |/
  | x  2:f91e97234c2b  draft  fix bug 15 (v1)
  |/
  @  1:de6151c48e1c  public  fix bug 37
  |
  ~
  $ hg --hidden -R ../public shortlog -G -r 1::
  o  2:540ba8f317e6  public  implement feature X (v3)
  |
  o  1:de6151c48e1c  public  fix bug 37
  |
  ~

How do things look in the review repo?
  $ cd ../review
  $ hg --hidden shortlog -G -r 1::
  o  6:540ba8f317e6  public  implement feature X (v3)
  |
  | x  5:0eb74a7b6698  draft  implement feature X (v2)
  |/
  | x  4:193657d1e852  draft  implement feature X (v1)
  |/
  | o  3:cbdfbd5a5db2  draft  fix bug 15 (v2)
  |/
  | x  2:f91e97234c2b  draft  fix bug 15 (v1)
  |/
  @  1:de6151c48e1c  public  fix bug 37
  |
  ~

Meantime, Alice is back from lunch. While she was away, Bob approved
her change, so now she can publish it.
  $ cd ../alice
  $ hg --hidden shortlog -G -r 1::
  @  3:cbdfbd5a5db2  draft  fix bug 15 (v2)
  |
  | x  2:f91e97234c2b  draft  fix bug 15 (v1)
  |/
  o  1:de6151c48e1c  public  fix bug 37
  |
  ~
  $ hg outgoing -q ../public
  3:cbdfbd5a5db2
  $ hg push ../public
  pushing to ../public
  searching for changes
  remote has heads on branch 'default' that are not known locally: 540ba8f317e6
  abort: push creates new remote head cbdfbd5a5db2 with bookmark 'bug15'!
  (pull and merge or see 'hg help push' for details about pushing new heads)
  [255]
  $ hg pull ../public
  pulling from ../public
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files (+1 heads)
  2 new obsolescence markers
  new changesets 540ba8f317e6
  (run 'hg heads' to see heads, 'hg merge' to merge)
  $ hg log -G -q -r 'head()'
  o  4:540ba8f317e6
  |
  ~
  @  3:cbdfbd5a5db2
  |
  ~
  $ hg --hidden shortlog -G -r 1::
  o  4:540ba8f317e6  public  implement feature X (v3)
  |
  | @  3:cbdfbd5a5db2  draft  fix bug 15 (v2)
  |/
  | x  2:f91e97234c2b  draft  fix bug 15 (v1)
  |/
  o  1:de6151c48e1c  public  fix bug 37
  |
  ~

Alice rebases her draft changeset on top of Bob's public changeset and
publishes the result.
  $ hg rebase -d 5
  rebasing 3:cbdfbd5a5db2 "fix bug 15 (v2)" (bug15)
  $ hg push ../public
  pushing to ../public
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files
  2 new obsolescence markers
  $ hg push ../review
  pushing to ../review
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 0 changes to 1 files
  1 new obsolescence markers
  obsoleted 1 changesets
  updating bookmark bug15

Figure SG08: review and public changesets after Alice pushes.
  $ hg --hidden -R ../review shortlog -G -r 1::
  o  7:a06ec1bf97bd  public  fix bug 15 (v2)
  |
  o  6:540ba8f317e6  public  implement feature X (v3)
  |
  | x  5:0eb74a7b6698  draft  implement feature X (v2)
  |/
  | x  4:193657d1e852  draft  implement feature X (v1)
  |/
  | x  3:cbdfbd5a5db2  draft  fix bug 15 (v2)
  |/
  | x  2:f91e97234c2b  draft  fix bug 15 (v1)
  |/
  @  1:de6151c48e1c  public  fix bug 37
  |
  ~
  $ hg --hidden -R ../public shortlog -G -r 1::
  o  3:a06ec1bf97bd  public  fix bug 15 (v2)
  |
  o  2:540ba8f317e6  public  implement feature X (v3)
  |
  o  1:de6151c48e1c  public  fix bug 37
  |
  ~
  $ cd ..

Setup for "cowboy mode" shared mutable history (to illustrate divergent
and bumped changesets).
  $ rm -rf review alice bob
  $ hg clone public alice
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ hg clone public bob
  updating to branch default
  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ cat >> alice/.hg/hgrc <<EOF
  > [phases]
  > publish = false
  > EOF
  $ cp alice/.hg/hgrc bob/.hg/hgrc

Now we'll have Bob commit a bug fix that could still be improved::

  $ cd bob
  $ echo 'pretty good fix' >> file1
  $ hg commit -u bob -m 'fix bug 24 (v1)'
  $ hg shortlog -r .
  4:2fe6c4bd32d0  draft  fix bug 24 (v1)

Since Alice and Bob are now in cowboy mode, Alice pulls Bob's draft
changeset and amends it herself. ::

  $ cd ../alice
  $ hg pull -u ../bob
  pulling from ../bob
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files
  new changesets 2fe6c4bd32d0
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  $ echo 'better fix (alice)' >> file1
  $ hg amend -u alice -m 'fix bug 24 (v2 by alice)'

Bob implements a better fix of his own::

  $ cd ../bob
  $ echo 'better fix (bob)' >> file1
  $ hg amend -u bob -m 'fix bug 24 (v2 by bob)'
  $ hg --hidden shortlog -G -r 3::
  @  5:a360947f6faf  draft  fix bug 24 (v2 by bob)
  |
  | x  4:2fe6c4bd32d0  draft  fix bug 24 (v1)
  |/
  o  3:a06ec1bf97bd  public  fix bug 15 (v2)
  |
  ~

Bob discovers the divergence.
  $ hg pull ../alice
  pulling from ../alice
  searching for changes
  adding changesets
  adding manifests
  adding file changes
  added 1 changesets with 1 changes to 1 files (+1 heads)
  1 new obsolescence markers
  2 new content-divergent changesets
  new changesets e3f99ce9d9cd
  (run 'hg heads' to see heads, 'hg merge' to merge)

Figure SG09: multiple heads! divergence! oh my!
  $ hg --hidden shortlog -G -r 3::
  *  6:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
  |
  | @  5:a360947f6faf  draft  fix bug 24 (v2 by bob)
  |/
  | x  4:2fe6c4bd32d0  draft  fix bug 24 (v1)
  |/
  o  3:a06ec1bf97bd  public  fix bug 15 (v2)
  |
  ~
  $ hg --hidden shortlog -r 'successors(2fe6)'
  5:a360947f6faf  draft  fix bug 24 (v2 by bob)
  6:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)

Use evolve to fix the divergence.
  $ cat > editor.sh <<EOF
  > #!/bin/sh
  > cat > \$1 <<ENDOF
  > fix bug 24 (v2 by bob)
  > ENDOF
  > EOF

  $ HGEDITOR='sh ./editor.sh' HGMERGE=internal:other hg evolve --content-divergent
  merge:[5] fix bug 24 (v2 by bob)
  with: [6] fix bug 24 (v2 by alice)
  base: [4] fix bug 24 (v1)
  merging "other" content-divergent changeset 'e3f99ce9d9cd'
  0 files updated, 1 files merged, 0 files removed, 0 files unresolved
  working directory is now at 711ede2d7a26
  $ hg log -q -r 'contentdivergent()'

Figure SG10: Bob's repository after fixing divergence.
  $ hg --hidden shortlog -G -r 3::
  @  7:711ede2d7a26  draft  fix bug 24 (v2 by bob)
  |
  | x  6:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
  |/
  | x  5:a360947f6faf  draft  fix bug 24 (v2 by bob)
  |/
  | x  4:2fe6c4bd32d0  draft  fix bug 24 (v1)
  |/
  o  3:a06ec1bf97bd  public  fix bug 15 (v2)
  |
  ~
  $ hg --hidden shortlog -r 'precursors(711ede2d7a26)'
  5:a360947f6faf  draft  fix bug 24 (v2 by bob)
  6:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
  $ cat file1
  Do stuff.
  pretty good fix
  better fix (alice)