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

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?

Related

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

hg remove * deleted my files! How do I get them back?

Folks, I need your help!
I tried to push my hg repository to bitbucket for the first time. It didn't work and I thought this was because the project is to huge. Therefore, I wanted to push only one single file.
Since I did "hg add *" before, I wanted to revoke this, and typed "hg remove *" and now it DELETED FILES ON MY COMPUTER. But not all of them, only some...
I need these files back, how do I do it? Please tell me they're not gone, please please please.
Thank you so much for your help!!
This is my command history:
518 hg commit commit_test.txt -m "first commit"
519 hg add commit_test.txt
520 hg commit -m "test"
521 ls -ll
522 ls -la
523 cd .hg/
524 ls
525 ls -la
526 pico hgrc
527 cd ..
528 hg status
529 hg add commit_test.txt~
530 hg add commit_test.txt
531 hg commit -m "blabla"
532 hg push
533 hg add commit_test.txt
534 hg commit -m "maaan"
535 hg status
536 hg remove *
537 hg status
538 hg commit -m "bla"
539 ls
540 hg add test.txt
541 hg commit -m "test"
542 hg push
543 hg revert
544 hg revert --all
545 history
546 hg add *
547 hg add -r *
548 hg help add
549 hg add -S *
550 cd gui_relabel/
551 hg add *
552 cd images/
553 hg add *
554 cd ..
555 hg revert all
556 hg revert *
557 history
Here is what hg log gives me:
$ hg log
changeset: 6:4726f671ae96
tag: tip
user: KG <...#gmail.com>
date: Wed Dec 04 12:21:30 2013 +0100
summary: test
changeset: 5:55b3158def38
user: KG <...#gmail.com>
date: Wed Dec 04 12:17:19 2013 +0100
summary: bla
changeset: 4:ae0dd836586d
user: KG <...#gmail.com>
date: Wed Dec 04 12:14:50 2013 +0100
summary: blabla
changeset: 3:0249fdc26fa7
user: KG <...#gmail.com>
date: Wed Dec 04 12:13:59 2013 +0100
summary: test
changeset: 2:40bdcf4d2104
user: KG <...#gmail.com>
date: Wed Dec 04 12:12:37 2013 +0100
summary: first commit test
changeset: 1:f9e20020ca1d
user: KG <...#gmail.com>
date: Sun Nov 10 14:54:46 2013 +0100
summary: first commit
changeset: 0:7a8edcee06ff
user: KG <...#gmail.com>
date: Mon Nov 04 20:36:41 2013 +0100
summary: blabla
Your files are not gone. Mercurial does not throw away data, that is one of the first rules of the system.
To explain what hg remove did to your files, let us look at the cases one by one. A file in your working copy can be in one out of a handful different states: it can be modified, added, removed, missing, unknown, ignored, or clean.
I've prepared a working copy that looks like this:
$ hg status --all
M a
A b
R c
! d
? e
I f
C g
The files a to g are in the seven states I mentioned above. We can now talk about what happens when you try to remove these files:
A modified file (a) is not removed:
$ hg remove a
not removing a: file is modified (use -f to force removal)
An added file (b) is also not removed:
$ hg remove b
not removing b: file has been marked for add (use forget to undo)
A removed file (c) is no longer present in the working copy, so nothing more happens.
A missing file (d) is no longer present in the working copy, so nothing more happens.
An untracked file (e) is not removed:
$ hg remove e
not removing e: file is untracked
An ignored file (f) is not removed (since it is not tracked):
$ hg remove f
not removing f: file is untracked
A clean file (g) is removed.
The only type of file that hg remove will actually remove from your working copy is a clean file. A clean file is already committed, so the content is safely stored in the repository. You can get it back with hg revert:
$ hg revert g
$ hg status --all
M a
A b
R c
! d
? e
I f
C g
The file g is back with the same content as it had before you removed it.
It looks like you could run
hg backout 5
You can read more about backout if you like

How to display outgoing diff without merges?

When using mercurial, when working on a large change, I will do several commits (as safe points, or share my progress with coworkers).
Whe I am done, I want to push my changes into the main repository. Before I do that, though, I will want to do a "hg pull -u && hg merge"to get changes that occured since my last pull, and review my changes.
Because I have several changesets, running hg diff on each of those is not a good solution.
I tried running hg diff -c"outgoing() and not merge()" to only show the diff for my outgoing changesets (without merge ones, as this tends to only add noise which I want to avoid).
However, it is still not ok for me, as mercurial seems to skip some information, and I do not understand on what basis. Please refer to the scenario below:
full scenario:
# clean working directory
rm -fr base clone
#prepare reference repo
mkdir base; cd base
hg init
touch 1.txt
echo " 1\n2" >>1.txt
hg add 1.txt
touch 2.txt
hg add 2.txt
hg commit -m"initial commit"
cd ..
hg clone base clone
cd base
#update ref repo.
echo "foo" >> 1.txt
hg commit -m"update file on remote repository"
#make changes locally
cd ../clone
echo "foo" >> 2.txt
hg commit -m "update initial file"
#now we are ready to push
hg pull -u && hg merge
hg commit -m"merge"
#actually...
sed -i -e 's/foo/bar/' 2.txt
hg commit -m"changed my mind"
hg out
changeset: 1:fce14ac089b2
date: Thu Nov 14 11:17:08 2013 +0100
summary: update initial file
changeset: 3:1967c50242c0
parent: 1:fce14ac089b2
parent: 2:2cdaf75afc6d
date: Thu Nov 14 11:17:10 2013 +0100
summary: merge
changeset: 4:120a0b8a0ede
tag: tip
date: Thu Nov 14 11:18:54 2013 +0100
summary: changed my mind
#try to display my changes
hg diff -c"outgoing() and not merge()"
--- a/2.txt Thu Nov 14 11:17:10 2013 +0100
+++ b/2.txt Thu Nov 14 11:18:54 2013 +0100
## -1,1 +1,1 ##
-foo
+bar
#only one change here!
#but
hg log -r"outgoing() and not merge()"
changeset: 1:fce14ac089b2
date: Thu Nov 14 11:17:08 2013 +0100
summary: update initial file
changeset: 4:120a0b8a0ede
tag: tip
date: Thu Nov 14 11:18:54 2013 +0100
summary: changed my mind
#is ok
So, could anyone please explain to me why mercurial skips changeset fce14ac089b2 entirely? What I expect is a consolidated output, i.e something like:
--- a/2.txt
+++ b/2.txt
## -1,1 +1,1 ##
+bar
Thanks a lot in advance.
I think the problem is a misunderstanding of what hg diff -c aka hg diff --change does. It takes a single revision id and shows you the change made by that one revision relative to its left parent.
You're calling:
hg diff -c"outgoing() and not merge()"
which yields multiple revisions (it's a revision set), but only one of them is being used. You're essentially seeing the output of:
hg diff --change 120a0b8a0ede
If what you're trying to do is see all of your outgoing changes lumped together in one diff you don't want --change/-c.
If you think about it the revset outgoing() could contain many changeset from many branches so smooshing them all into one diff isn't necessarily possible at all.
If the view you're trying to get is "how does the most recent head on branch default locally compare to the most recent head on default remotely" you need to know the node id of the most recent head on default, and then locally you'd just run:
hg diff node_id_of_most_recent_head_on_default_at_remote_site
This isn't guaranteed, as I expect that there's some way to have a change graph where the last public ancestor isn't the change-set you're after, but...
> hg diff -r "last(ancestors(.) and public())"
diff -r 5579be654db4 2.txt
--- a/2.txt Sat Nov 16 11:03:06 2013 +0000
+++ b/2.txt Sat Nov 16 11:29:34 2013 +0000
## -0,0 +1,1 ##
+bar

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.

pretxnchangegroup hook cannot see entire changeset

we're trying to find a way to see the entire changeset of one or more incoming revisions in a mercurial repository inside the pretxnchangegroup hook. We use version 1.6.3.
We can get the first incoming change with $HG_NODE, but hg tip still points to the oldest, committed change, not to the one that we're about to tack on. The same for hg log -rNode:
We cannot even seem to get the diff of $HG_NODE in this hook, hg log just says "unknown revision"
It seems like this is related to http://groups.google.com/group/mercurial_general/browse_thread/thread/9321b94b08ab04b9
Has anyone had the same problem and solved it somehow?
It should definitely be the case that both tip and log reflect the post-arrival information. Are you sure that the directory in which you're running those commands is that of the repository triggehg clone hooktest hooktest-clone
ring the hook? The only way I could see that not being the case were if you were using hg -R, which you'd know.
Here's a test script you should be able to paste into a (unix or cygwin) shell:
hg init hooktest
echo this >> hooktest/afile
echo -e '[hooks]\npretxnchangegroup = hg log && hg tip' >> hooktest/.hg/hgrc
hg -R hooktest commit -A -m 'initial commit'
hg clone hooktest hooktest-clone
echo more >> hooktest-clone/afile
hg -R hooktest-clone commit -m 'second commit'
hg -R hooktest-clone push
When I paste that I get:
ry4an#hail [~/hg] % hg init hooktest
ry4an#hail [~/hg] % echo this >> hooktest/afile
ry4an#hail [~/hg] % echo -e '[hooks]\npretxnchangegroup = hg log && hg tip' >> hooktest/.hg/hgrc
ry4an#hail [~/hg] % hg -R hooktest commit -A -m 'initial commit'
adding afile
ry4an#hail [~/hg] % hg clone hooktest hooktest-clone
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
ry4an#hail [~/hg] % echo more >> hooktest-clone/afile
ry4an#hail [~/hg] % hg -R hooktest-clone commit -m 'second commit'
ry4an#hail [~/hg] % hg -R hooktest-clone push
pushing to /home/msi/ry4an/hg/hooktest
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
changeset: 1:ab2cec57f878
tag: tip
user: Ry4an Brase <ry4an#msi.umn.edu>
date: Wed Nov 03 09:10:40 2010 -0500
summary: second commit
changeset: 0:30db2e527437
user: Ry4an Brase <ry4an#msi.umn.edu>
date: Wed Nov 03 09:10:39 2010 -0500
summary: initial commit
changeset: 1:ab2cec57f878
tag: tip
user: Ry4an Brase <ry4an#msi.umn.edu>
date: Wed Nov 03 09:10:40 2010 -0500
summary: second commit
ry4an#hail [~/hg] %
Where you can see that both 'hg log' and 'hg tip' show the new changeset in the hook.
Does that test run for you?