How to check which branch you are on with mercurial - mercurial

What is the best way to check which branch I am on with mercurial?
hg log -l 5
This seems to show me the latest commits in the repo and not about working state as git would, so I'm looking for something like git status I suppose, which would tell me what branch I am on. hg status doesn't show me anything.

You can use the hg identify command with the -b for branch option:
C:\Some\Repository> hg identify -b
default

hg branch. I suggest at least reading hg help once :^)

$ hg branch
You can just always use the grep with a keyword to search.
In this case,
$ hg help | grep branch`
Gives you:
branch set or show the current branch name
branches list repository named branches
graft copy changes from other branches onto the current branch
heads show branch heads

You could use hg sum
for example, say you have two branches, A and B
[root#B6LEB1 ATS]# hg update A
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
[root#B6LEB1 ATS]# hg sum
parent: 1787:3f06e1a0260a
made A
branch: A
commit: (clean)
update: (current)
[root#B6LEB1 ATS]# hg update B
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
[root#B6LEB1 ATS]# hg sum
parent: 1788:7ff3c507efd9 tip
made B
branch: B
commit: (clean)
update: (current)

You also might want to specify the currently checked-out version explicitly. Then the output of hg log will return what you look for:
hg log -r.

Related

How to merge a feature branch to default with subrepositories with Mercurial

I have numerous projects with subrepositories:
/project <- Main repository
/project/src <- Source code subrepository (subrepository to /project)
/project/src/module <- Module subrepository (subrepository to /project/src repository)
I've now worked on a feature branch (feature1) which has had a few revisions, which I'd now like to merge back into the default branch. The default branch hasn't had any changes since the feature1 branch was created.
I've tried merging the branch to default however end up with some strange things happening in the subrepositories.
I've followed the instructions in this other post, and get the following results:
$ hg checkout default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge feature1
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg status -S
M .hgsubstate
$ hg commit -S -m "branch merge test"
nothing changed
$ hg branches
default 19:c2398dc23428
feature1 17:98dc0efbad90 (inactive)
What's strange is that even though many files were changed in the module subrepository, the merge only stated that 1 file was updated. I'm assuming that this happens to be the .hgsubstate.
When I explicitly update the subrepository, then I get the following:
$ cd src/module
$ hg update
39 files updated, 0 files merged, 23 files removed, 0 files unresolved
$ cd ../..
$ hg commit -S -m "feature1 merge"
committing subrepository src
$ hg status -S
M .hgsubstate
So after doing a hg update to bring all the changes into the working directory, I see the changes in the module subrepository that I need to commit. However, .hgsubstate always remains in the modified state. I've tried hg remove. I've tried hg forget. But no matter what I do, it still is marked when I do a hg status.
So my questions are:
Was the process I took to merge the branch in correct (considering subrepositories are present)?
Is it necessary to do a hg update in the subrepositories to make the main repository recognize the changes?
Why is .hgsubstate misbehaving?
You don't say which version of hg you are using - subrepo support has changed a certain amount over time. I've just tried something like your test with 3 subrepo levels in hg v2.8 and it works for me.
When you got a dirty .hgsubstate at the top level, that is normal when you commit a subrepo. [If only a subrepo has been committed independently, only the .hgsubstate will be dirty at the top level.] If you then go up to the top level and commit at that level the .hgsubstate will be committed, and everything is fine. Remember, the top level repo tracks subrepos in a similar fashion to files - it commits a particular changeset from the subrepo at each top level commit.
FWIW. The recommended practice is to commit subrepos separately, i.e. avoid committing at the top level if the subrepos are dirty. The reason is that the subrepos often require a different commit message - they are subrepos for a reason after all; but you can commit at the top level if you wish. In your case with 3 levels the sequence would be:
cd src/module
hg commit -m "src/module commit reason"
cd ..
hg commit -m "src commit reason"
cd ..
hg commit -m "top level reason"
It was intended that subrepos would change infrequently, e.g. third party libraries. If your subrepos are going to change frequently, you and your team will have to be vigilant to avoid mistakes, especially when merging with other peoples work. [But given the date of the question you've probably worked that out yourself by now.]

Mercurial: "undoing" two or more commits

In How do I do a pristine checkout with mercurial? Martin Geisler discuss how to remove already Mercurial commit'ed files using:
hg strip "outgoing()"
But what if I I want to keep my added files which went into "outgoing()" - example:
Two users a and b — starting on the same changeset
User a:
echo "A" > A.txt; hg ci -M -m ""; hg push
User b (forgets to run hg pull -u):
echo "B" > B.txt; hg ci -M -m "" B.txt;
echo "C" > C.txt; hg ci -M -m "" C.txt;
If user b run hg strip "outgoing()" then B.txt and C.txt are lost. hg rollback is not an option since there are two commits.
Can user b revert his files as "locally added - nontracked", then do hg pull -u, which gets A.txt, then handle the add/commit/push for B.txt and C.txt later?
Martin Geisler answered this earlier in the mentioned thread (a comment which I deleted and moved here:
hg update "p1(min(outgoing()))"
hg revert --all --rev tip
hg strip "outgoing()"
hg pull -u
Now user c can finalize his work in the new files B.txt and C.txt and commit+push those.
Other ways to do this?
You could but, by doing so, you are working against one of the biggest features of a DVCS like mercurial, that is, to easily and reliably handle the merging of multiple lines of development as in your case. If user b's goal is to have a line of development with all three changes applied, then the standard way to do that in hg would be to just go ahead and do an hg pull -u which will create a new head containing the change(s) from user a (and any other changes pushed to repo used for pulling) and then use hg merge to merge the two heads, the head containing user b's two change sets and the other containing user a's change set (as pulled). In a simple case like this one with no overlapping changes, hg should do all the right things by default.
$ hg pull -u
[...]
added 1 changesets with 1 changes to 1 files (+1 heads)
not updating: crosses branches (merge branches or update --check to force update)
$ hg merge
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg ci -m "merge"
If there were conflicts between the two heads (i.e. both users committed changes to the same files), there might need to be conflict resolution editing as part of the merge; hg will tell you if that is the case.
Another option is the rebase extension. With your scenario:
A and B start with the same history.
A commits and pushs a change.
B commits two changes, but can't push because of A's commit.
B pulls A's change.
B runs hg rebase and pushes.
Before rebase:
Common ---------------------------- A (tip)
\
B1 - B2 (working parent)
After:
Common - A - B1 - B2 (tip, working parent)

Mercurial - see list of files that need to be manually merged?

Is there a Mercurial command you can use after an hg pull to see a list of all files that will be need to be manually merged (ie: that have conflicts) when doing an hg merge?
hg resolve --list
From the documentation:
Merges with unresolved conflicts are often the result of non-interactive merging using the internal:merge configuration setting, or a command-line merge tool like diff3. The resolve command is used to manage the files involved in a merge, after hg merge has been run, and before hg commit is run (i.e. the working directory must have two parents).
Edit 5 January 2012:
(I received an up vote for this answer today so I revisited it. I discovered that I misunderstood the question.)
The question is "I have performed a pull from a remote repository and have not yet performed a merge. Can I see what conflicts will be created upon performing the merge?"
My answer above is clearly wrong. After reading through the linked documentation, I do not think there is a built-in method for doing this. However, there is a way to do it without ruining your working source tree.
Let's assume you have cloned repository A from some remote source to repository B on your local system, i.e. hg clone http://hg.example.com/A B. After doing so, you make changes to your local repository, B, that involve at least one commit. In the meantime, changes have been made to repository A so that when you do a pull you get a message indicated new changesets have been added and heads have been created.
At this point, you can do hg heads to list the two changesets that will be involved in a merge. From this information, you can issue a status command to list the differences between the heads. Assuming the revision numbers in your repository B, according to the heads list, are "1" and "2", then you can do hg status --rev 1:2 to see a list of the changes.
Of course, this doesn't really tell you if conflicts will occur when you do a merge. Since there isn't a command that will show you this, you will have to "preview" the merge by cloning to a new repository and doing the merge there. So, hg clone B C && cd C && hg merge. If you are satisfied with the result of this merge you can do hg com -m 'Merging complete' && hg push && cd ../ && rm -rf C.
It's a bit of a process, but it keeps your current source tree clean if the merge turns out to be a disaster. You might also find this description of working with public repositories helpful.
Unless I'm misreading it myself, the answers above don't seem to address the question that I think is being asked: I have two branches in my repository that I'd like to merge, and I want to know what conflicts will come up (e.g., before stepping through the conflict resolutions one-by-one.)
To do this, I would merge with the :merge3 tool (which tries to merge automatically, but leaves conflicts unresolved) and then use hg resolve --list — or just look at the output of merge command — to see the conflicts.
hg merge <otherbranch> --tool :merge3
hg resolve -l
If you didn't actually want to merge in the end (if you just want to see what would conflict) you can run hg update -C afterwards to undo the merge.
If you do want to finish the merge, you can run hg resolve <filepath> for each file, or just hg resolve --all to step through all that remain with conflicts, before you hg commit the merge changeset.
You can use the --rev option of hg stat with a pair of revisions to see what file differences exist between the two. See below for a slightly verbose but detailed example:
First we start by making a new repository:
[gkeramidas /tmp]$ hg init foo
[gkeramidas /tmp]$ cd foo
Then add a single file called foo.txt to the new repository:
[gkeramidas /tmp/foo]$ echo foo > foo.txt
[gkeramidas /tmp/foo]$ hg commit -Am 'add foo'
adding foo.txt
[gkeramidas /tmp/foo]$ hg glog
# 0[tip] b7ac7bd864b7 2011-01-30 18:11 -0800 gkeramidas
add foo
Now add a second file, called bar.txt as revision 1:
[gkeramidas /tmp/foo]$ echo bar > bar.txt
[gkeramidas /tmp/foo]$ hg commit -Am 'add bar'
adding bar.txt
Go back to revision 0, and add a third file, on a different head. This is done to simulate a pull from someone else who had cloned the same repository at its starting revision:
[gkeramidas /tmp/foo]$ hg up -C 0
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
[gkeramidas /tmp/foo]$ echo koko > koko.txt
[gkeramidas /tmp/foo]$ hg commit -Am 'add koko'
adding koko.txt
created new head
[gkeramidas /tmp/foo]$ hg glog
# 2[tip]:0 e5d80abdcb06 2011-01-30 18:12 -0800 gkeramidas
| add koko
|
| o 1 a2d0d0e66ce4 2011-01-30 18:12 -0800 gkeramidas
|/ add bar
|
o 0 b7ac7bd864b7 2011-01-30 18:11 -0800 gkeramidas
add foo
Now you can use hg stat to see what file differences exist between any pair of revisions, e.g. the changes from rev 0 to rev 1 added 'bar.txt' to the file list:
[gkeramidas /tmp/foo]$ hg stat --rev 0:1
A bar.txt
The changes from rev 0 to rev2 added 'koko.txt' to the file list:
[gkeramidas /tmp/foo]$ hg stat --rev 0:2
A koko.txt
But more interestingly, the changes from rev 1 to rev 2 involve two file manifest changes. (1) 'koko.txt' was added in rev 2, and (2) 'bar.txt' exists in rev 1 but is missing from rev 2, so it shows as a 'removed' file:
[gkeramidas /tmp/foo]$ hg stat --rev 1:2
A koko.txt
R bar.txt
I think hg status is what you are looking for.
You may want to read this chapter from Mercurial: The Definitive Guide
http://hgbook.red-bean.com/read/mercurial-in-daily-use.html

mercurial push certain revision

I have searched here, but haven't found any question related to this. I got a problem like this in mercurial:
I manage open source project in bitbucket, so i have clone of the source code in my local. But I also using that project for my own live site, so I made 2 clone of bitbucket repo
Bitbucket Repo
|
==local_clone1
|
==local_clone2-> commit1 => commit2 => commit3
(personalization) (bug fix) (add feature)
The question is, I want to push commit2 and commit3 back to local_clone1, so later on I can push to Bitbucket repo. But don't want to push commit1, since it has my personal data.
Wondering how we do that in mercurial?
This can be done without too much difficulty in this case. See Removing history in the Mercurial guide for more information.
Here's the basics of what you'll need to do:
Go to local_clone2
Get the revision number (hg tip will show you) from the current number. We'll call it 731.
hg export 730-731 > ../local_clone1/changes.diff (or wherever you like)
Go to local_clone1
hg import changes.diff
You may need to edit things manually; refer to that guide for more info in that case.
Here are a couple of options:
backout
Given a history constructed as:
hg init db
cd db
echo >file1
hg ci -Am clone # rev 0
echo >file2
hg ci -Am personalization # rev 1
echo >file3
hg ci -Am bugfix # rev 2
echo >file4
hg ci -Am feature # rev 3 <tip>
Then if the current working directory is the tip, the following commands will "undo" the personalization revision:
hg backout 1
hg ci -m backout
The advantage is history remains immutable, but shows the addition and backout of the personalization changeset.
Mercurial Queues
With the mq extension, history can be edited to remove a changeset:
hg qimport -r 1:3 # convert changesets 1-3 to patches
hg qpop -a # remove all patches (can't delete an applied patch)
hg qdel 1.diff # delete rev 1's patch
hg qpush -a # reapply remaining patches
hg qfin -a # convert all applied patches back to changesets.
The advantage is the personalization changeset disappears. The disadvantage is the changeset hashes change due to the history edit, so this should never be done to changesets that have already been pushed to others. There is also the risk of a mistake editing history.

How to compare two revisions in Mercurial?

I need to know what files have been added/modified/removed between two revisions. What I do:
hg status --rev 10:11
It looks okay. But when I have only one revision (initial = 0) it doesn't work.
# not work
hg status --rev 0:0
# also not work as I want
hg status --rev 0
There is no revision -1.
The special revision null is used to indicate the parent of revision 0. You can use
hg status --rev null:0
to see the changes in the first revision.
hg status --change [rev]
ie,
hg status --change 0
and
hg log -v
You might want to look at the output of hg log -v. For each changeset, it should list the files modified in that changeset. If you had a particular changeset in mind, add the -r switch to specify it.