How to hg bundle only changes in a branch? - mercurial

I have tried this:
$ hg bundle -b my-branch ../my-branch-bundle.hg
searching for changes
no changes found
Then this:
$ hg bundle --all --branch my-branch ../my-branch-bundle.hg
7191 changesets found
... but my branch has only 3 commits? Then also this:
$ hg bundle --base null --branch my-branch ../my-branch-bundle.hg
7191 changesets found
How to hg bundle only the changes for a given branch?!

hg bundle bundles each specified revision (-r) and assumes the destination repository has all the revisions (and their ancestors) specified by the --base option.
So one way to get only a small branch of 3 changesets is to specify with --base the first changeset branched from, and specify of the first changeset of the branch and its descendants.
For example, given:
o changeset: 5:f429f686e698
| branch: test
|
o changeset: 4:e02923c7302b
| branch: test
|
o changeset: 3:076f442d4d3b
| branch: test
|
| # changeset: 2:dab4279642cb
|/
o changeset: 1:233d09b80d63
|
o changeset: 0:6818527e85ac
Use:
hg bundle --base 1 --rev heads(descendants(3))

Related

How do I update to the last public revision in my repository?

o 911e74cd 44 minutes ago master
|
| # f085ae95 3 minutes ago
| | Testing
| |
| o 4431b579 Today at 11:24
|/ Feature
|
o 4ab195c4 Today at 04:59
I am currently on revision f085ae95 and I would like to use one hg update command to get to 4ab195c4, which is the last ancestor that is on the public branch in the repository.
You can literally do:
hg update 4431b579
and that should work.
This will update the files in your working folder to whatever state they had in the referenced changeset.
You could also use:
hg up -r -2
to go back 2 revisions from the working folder, which I think would do the same thing.
hg log -r "last(public() and ancestors(.))" --template "{node}" will print out the hash of the last commit on the public branch that is also an ancestor of the current commit. As such you can now chain command calss via:
hg update `hg log -r "last(public() and ancestors(.))" --template "{node}"`
or
hg rebase -s `<commit-you-want-to-rebase>` -d `hg log -r "last(public() and ancestors(.))" --template "{node}"`

hg shelve created a commit, I don't understand

I'm a bit confused by hg shelve because the documentation is rather sparse. Somehow I got a commit in my log of the form:
changeset: 29:ad47ed1ca915
parent: 27:afca280f2884
user: shelve#localhost
date: Wed Jun 08 15:30:36 2016 -0600
summary: changes to: ...
I'm confused as to where this came from. It was my understanding that shelve was just stuffing things on the local machine and that they wouldn't get in the history. Am I misunderstanding that?
Here's my hg command history:
hg status
hg shelve list
hg shelve --list
hg unshelve
hg unshelve
hg resolve
hg resolve -all
hg resolve --all
hg resolve --all
hg clone a/ b
# By this point we have the commit (since 28 is after 27)
hg update -r 28
EDIT:
Ok, so the problem seems to be a partial unshelve. However, because I pull the changesets else where now I'm stuck with the changesets and am not sure what to do :(
EDIT2: Here's an example of how to cause this problem:
~ $ cd tmp
~/tmp $ mkdir shelve shelve/a
~/tmp $ cd shelve/a
~/tmp/shelve/a $ hg init
~/tmp/shelve/a $ echo a > a
~/tmp/shelve/a $ hg add a
~/tmp/shelve/a $ hg commit -m "a as a"
~/tmp/shelve/a $ cd ..
~/tmp/shelve $ hg clone a b
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
~/tmp/shelve $ cd b
~/tmp/shelve/b $ echo aa > a
~/tmp/shelve/b $ hg commit -m "a as aa"
~/tmp/shelve/b $ cd ../a
~/tmp/shelve/a $ echo aaa > a
~/tmp/shelve/a $ hg shelve
shelved as default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
~/tmp/shelve/a $ hg pull -u ../b
pulling from ../b
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
~/tmp/shelve/a $ hg unshelve
unshelving change 'default'
rebasing shelved changes
rebasing 2:6696488053d1 "changes to: a as a" (tip)
merging a
3 files to edit
was merge successful (yn)? n
merging a failed!
unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
~/tmp/shelve/a $ hg heads
changeset: 2:6696488053d1
tag: tip
parent: 0:845abf4a2513
user: shelve#localhost
date: Thu Jun 16 19:44:05 2016 -0600
summary: changes to: a as a
changeset: 1:e1f75f582f85
user: Alex Orange <crazycasta#gmail.com>
date: Thu Jun 16 19:44:05 2016 -0600
summary: a as aa
Here's my solution. Also shows a bit more of the problem. The problem comes if you do an hg pull with an unresolved unshelve.
~ $ cd tmp
~/tmp $ cd shelve/a
~/tmp/shelve/a $ hg resolve a
merging a
3 files to edit
continue: hg unshelve --continue
~/tmp/shelve/a $ cd ../b
~/tmp/shelve/b $ echo Cause failure
Cause failure
~/tmp/shelve/b $ hg pull ../a
pulling from ../a
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)
~/tmp/shelve/b $ hg heads
changeset: 2:6696488053d1
tag: tip
parent: 0:845abf4a2513
user: shelve#localhost
date: Thu Jun 16 19:44:05 2016 -0600
summary: changes to: a as a
changeset: 1:e1f75f582f85
user: Alex Orange <crazycasta#gmail.com>
date: Thu Jun 16 19:44:05 2016 -0600
summary: a as aa
~/tmp/shelve/b $ cd ../a
~/tmp/shelve/a $ hg unshelve --continue
rebasing 2:6696488053d1 "changes to: a as a" (tip)
unshelve of 'default' complete
~/tmp/shelve/a $ hg commit -m "a as aaa"
~/tmp/shelve/a $ cd ../b
~/tmp/shelve/b $ hg pull
pulling from /home/crazycasta/tmp/shelve/a
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
~/tmp/shelve/b $ echo Problem
Problem
~/tmp/shelve/b $ hg heads
changeset: 3:a804c9f51cd6
tag: tip
parent: 1:e1f75f582f85
user: Alex Orange <crazycasta#gmail.com>
date: Thu Jun 16 20:02:43 2016 -0600
summary: a as aaa
changeset: 2:6696488053d1
parent: 0:845abf4a2513
user: shelve#localhost
date: Thu Jun 16 19:44:05 2016 -0600
summary: changes to: a as a
~/tmp/shelve/b $ echo Solution
Solution
~/tmp/shelve/b $ hg strip -r 2
saved backup bundle to /home/crazycasta/tmp/shelve/b/.hg/strip-backup/6696488053d1-313495de-backup.hg
~/tmp/shelve/b $ hg heads
changeset: 2:a804c9f51cd6
tag: tip
user: Alex Orange <crazycasta#gmail.com>
date: Thu Jun 16 20:02:43 2016 -0600
summary: a as aaa

Is it possible to create a branch when having uncommitted changes?

In Mercurial repo:
1) I've checked out (updated) from default
2) I've edited something
3) I've realized I need a branch to experiment with my edits
4) When I try to create a branch Mercurial claims I have uncommitted changes
If I don't get mistaken, in git allows you to checkout -b in such situation. I need to create a branch and commit my changes there.
UPDATE
It turned out that hg is as smart as git, and ALLOWS creating branches when having uncommitted changes. So, the problem on step 4 had no relation to hg.
This works just fine for me:
ry4an#four:~$ hg init dan
ry4an#four:~$ cd dan
ry4an#four:~/dan$ echo text > afile
ry4an#four:~/dan$ hg commit -Am added
adding afile
ry4an#four:~/dan$ echo more >> afile
ry4an#four:~/dan$ hg branch newbranch
marked working directory as branch newbranch
(branches are permanent and global, did you want a bookmark?)
ry4an#four:~/dan$ hg commit -m another
ry4an#four:~/dan$ hg log
changeset: 1:84b54b473852
branch: newbranch
tag: tip
user: Ry4an Brase <ry4an-hg#ry4an.org>
date: Wed Dec 04 11:36:52 2013 -0500
summary: another
changeset: 0:b07d96580927
user: Ry4an Brase <ry4an-hg#ry4an.org>
date: Wed Dec 04 11:36:13 2013 -0500
summary: added
When I ran hg branch newbranch nothing was actually created. The hg branch command just tells Mercurial what branch the next commit should be on, and indeed when I did that commit the log shows it was on newbranch. I had uncommitted changes when I did the hg branch line and there was no warning or error saying I couldn't do it -- how, specifically, are you trying to create that branch?

Is there another way of removing multiple heads?

Let's say I have this:
hg init
touch a
hg add a
hg commit -m a
touch b
hg add b
hg commit -m b
hg up -r 0
touch c
hg add c
hg commit -m c
Now I will have multiple heads, because of the last commit. If, for example I want to keep the last head, the one created by commit c ( effectively discarding b, and all other commits made after the first ) , how could I do it? I played a little with mq's strip command, and I'm able to achieve what I want, but I'd like to know if there's another way.
Yes, there is another way. From your example above, the output of hg glog looks a bit like this:
# changeset: 2:925573c7103c
| tag: tip
| parent: 0:4fe26dfe856d
| user: Joel B Fant
| date: Thu Jul 28 23:20:45 2011 -0400
| summary: c
|
| o changeset: 1:9dc928176506
|/ user: Joel B Fant
| date: Thu Jul 28 23:20:24 2011 -0400
| summary: b
|
o changeset: 0:4fe26dfe856d
user: Joel B Fant
date: Thu Jul 28 23:20:12 2011 -0400
summary: a
If you clone test but specify a revision, it will only clone that revision and its ancestors. So if your repo's directory is TwoHeadsMightNotBeBetter, you can go to its parent directory and issue:
hg clone TwoHeadsMightNotBeBetter OneHeadIsFine -r 925573c7103c
I specified changeset id in that, but you could also use -r 2 instead, or even -r tip since it is currently the tip of that repo. Now when you go into the new clone and do hg glog, you have only one head:
# changeset: 1:925573c7103c
| tag: tip
| user: Joel B Fant
| date: Thu Jul 28 23:20:45 2011 -0400
| summary: c
|
o changeset: 0:4fe26dfe856d
user: Joel B Fant
date: Thu Jul 28 23:20:12 2011 -0400
summary: a
If you had 3 heads and wanted to keep 2, it would be a little different. You'd have to clone one of them with -r and the also specify -r on hg pull to pull specific branches.
You can also perform a dummy merge of the changeset containing b (changeset 1 in this case):
$ hg --config ui.merge=internal:fail merge 1
resolving manifests
getting b
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg revert --all --no-backup --rev .
removing b
$ hg status
R b
$ hg commit -m "Dummy merge -- eliminate b"
committed changeset 3:c163151f19df
$ ls
a c
Note that in this case you haven't rewritten any history or created any new repos -- particularly important if b had already been pushed to a centralized repo and pulled by others.

Mercurial move changes to a new branch

I have a number of changes that I committed to my local repository, but have not yet been pushed. Since on a feature is taking longer than expected, I want to swap these changes onto a named branch before I push. How can I do this?
As suggested by Mark, the MqExtension is one solution for you problem. IMHO a simpler workflow is to use the rebase extension. Suppose you have a history like this:
# changeset: 2:81b92083cb1d
| tag: tip
| summary: my new feature: edit file a
|
o changeset: 1:8bdc4508ac7b
| summary: my new feature: add file b
|
o changeset: 0:d554afd54164
summary: initial
This means, revision 0 is the base on which you started to work on your feature. Now you want to have revisions 1-2 on a named branch, let's say my-feature. Update to revision 0 and create that branch:
$ hg up 0
$ hg branch my-feature
$ hg ci -m "start new branch my-feature"
The history now looks like this:
# changeset: 3:b5939750b911
| branch: my-feature
| tag: tip
| parent: 0:d554afd54164
| summary: start new branch my-feature
|
| o changeset: 2:81b92083cb1d
| | summary: my new feature: edit file a
| |
| o changeset: 1:8bdc4508ac7b
|/ summary: my new feature: add file b
|
o changeset: 0:d554afd54164
summary: initial
Use the rebase command to move revisions 1-2 onto revision 3:
$ hg rebase -s 1 -d 3
This results in the following graph:
# changeset: 3:88a90f9bbde7
| branch: my-feature
| tag: tip
| summary: my new feature: edit file a
|
o changeset: 2:38f5adf2cf4b
| branch: my-feature
| summary: my new feature: add file b
|
o changeset: 1:b5939750b911
| branch: my-feature
| summary: start new branch my-feature
|
o changeset: 0:d554afd54164
summary: initial
That's it .. as mentioned in the comments to Mark's answer, moving around already pushed changesets generally is a bad idea, unless you work in a small team where you are able to communicate and enforce your history manipulation.
You can use the MqExtension. Let's say the changesets to move are revisions 1-3:
hg qimport -r 1:3 # convert revisions to patches
hg qpop -a # remove all them from history
hg branch new # start a new branch
hg qpush -a # push them all back into history
hg qfin -a # finalize the patches
I prefer the patch solution describe here by Mark Tolonen
What I have:
hg log -G
#default branch
# changeset: 3:cb292fcdbde1
|
o changeset: 2:e746dceba503
|
o changeset: 1:2d50c7ab6b8f
|
o changeset: 0:c22be856358b
What I want:
# changeset: 3:0e85ae268e35
| branch: feature/my_feature
|
o changeset: 2:1450cb9ec349
| branch: feature/my_feature
|
o changeset: 1:7b9836f25f28
| branch: feature/my_feature
|
/
|
o changeset: 0:c22be856358b
mercurials commands:
hg export -o feature.diff 1 2 3
hg update 0
hg branch feature/my_feature
hg import feature.diff
Here is the state of my local repository
# changeset: 6:0e85ae268e35
| branch: feature/my_feature
|
o changeset: 5:1450cb9ec349
| branch: feature/my_feature
|
o changeset: 4:7b9836f25f28
| branch: feature/my_feature
|
| o changeset: 3:cb292fcdbde1
| |
| o changeset: 2:e746dceba503
| |
| o changeset: 1:2d50c7ab6b8f
|/
|
o changeset: 0:c22be856358b
Now I need to delete the revisions 1 2 and 3 from my default branch.
You can do this with strip command from mq's extension.
hg strip removes the changeset and all its descendants from the repository.
Enable the extension by adding following lines to your configuration file (.hgrc or Mercurial.ini):
vim ~/.hgrc and add :
[extensions]
mq =
And now strip this repository on revision 1.
hg strip 1
and here we are
# changeset: 3:0e85ae268e35
| branch: feature/my_feature
|
o changeset: 2:1450cb9ec349
| branch: feature/my_feature
|
o changeset: 1:7b9836f25f28
| branch: feature/my_feature
|
o changeset: 0:c22be856358b
note: changesets are different but revisions are the same
For those inclined to use GUI
Go to Tortoise Hg -> File -> Settings then tick rebase .
Restart tortoise UI
Create new branch where you will be moving changes. Click on current branch name -> choose Open a new named branch -> choose branch name.
If changes you want to move have not been made public (e.g draft) go to 5. (If changes have already been published and you are not a senior dev you should talk to someone senior (get a scapegoat) as you might screw things up big time, I don't take any responsibility :) ).
Go to View -> Show Console (or Ctrl + L)
then write in console hg phase -f -d 2 - where 2 is lowest revision you will be moving to new branch.
Go to branch and revision (should be topmost revision if you are moving changes to new branch created in step 3.) Right Mouse -> Update
Go to branch and revsion you will be moving changes from Right Mouse -> Modify History -> Rebase
Click Rebase and pray there are no conflicts, merge if you must.
Push changes, at this point all revisions should still be draft.
Go to topmost revision in branch you were moving changes to Right Mouse -> Change Phase to -> Public.
Hope this saves you some time.