We have a repository myproject - as the repo is nearly ready for release we are creating myproject-1_0. Version 2 dev will continue in myproject while minor tweaks and bug fixes will go in myproject-1_0. What is the best way to merge myproject-1_0 changes into myproject?
Is this the best approach:
$ cd myproject
$ hg pull ../myproject-1_0
$ hg merge
$ hg commit -m 'Merge bugfix from 1.0 branch'
$ hg push
?
What would happen if we did this merge on Feb 1st, then we made more changes in myproject-1_0? Would we follow the steps again and the hg pull ../myproject-1_0 would just pull the changesets done after the pull on Feb 1st?
In the myproject repo, is there a way to do an hg log and determine which changesets came from myproject-1_0 and which ones came from myproject?
Are there any other recommendations about this general approach?
Questions in sequence:
Is this the best approach? - yes, unless you want to use named branches and keep everything in one repository
would just pull the changesets done after the pull on Feb 1st? - yes
is there a way to do an hg log and determine which changesets came from myproject-1_0? - no
Unfortunately, unless you start mucking about with named branches, changesets that originate in the other repository looks no different from the ones in your main repository.
So this is what Mercurial is designed to do
I would suggest taking a look at http://www.hginit.com. But what you're asking if when you pull changes will it only pull the changes since the last pull, yes. You can't tell which changesets came from a different clone though, only user names are tracked in the idea that you are thinking about.
If you want to know where things are coming from this is something you can do in commit messages.
Related
I cloned a project to my local directory and made a lot of changes. My current goal is to push my changed code to a new branch in the remote repository. And eventually this new branch will be merged back to default.
My problem is, because of some stupid effort in the past a few weeks to try to recover some missing files, I end up with a few branch names that I don't want being shown in public.
Here's what I have:
$hg branches
dev-v02 197:xxxxx
dev2 194:xxxxx
dev 183:xxxxx
qa 189:xxxxx
$hg branch
dev-v02
My question is, if I push my current branch dev-v02 to the remote repository by "hg push --new-branch", and this branch later get merged back to default, will the unwanted branches show up in history of default? And if so, is there a safe way to purge them?
I do NOT want to discard my changes. I just don't want the unwanted branches showing up in "hg branches" or "hg his" commands by whoever later clones the project from the remote repository. I searched online and found "hg strip" but I couldn't tell from the article if it would also remove the changes I've made. Thanks.
Edit: I just cloned my local repository by "hg clone -r 197 original-dir dest-dir" as suggested by both kevin and chessbot and now hg branches shows:
dev-02 192:xxxxx
qa 187:xxxxx (inactive)
I guess "qa" remains because I had pushed it to the remote as a QA branch and closed it later, and I just have to live with that. I will push from this new directory from now on. Thanks guys for your help.
Try hg push --new-branch -b dev-v02 to specify that you're pushing only that branch.
(See: https://www.mercurial-scm.org/repo/hg/help/push)
Another thing you could do: Clone the repository locally on your machine, strip out the branches you don't want, and then push that clone to the server. Then you retain your history locally without pushing it to everyone else.
It depends.
Branches are permanently associated with a commit. The branch is part of the commit, and contributes to the hash. Changing the branch of a commit in the past would alter all commit hashes from that point forward. This is quite different from Git, where a branch is little more than an ephemeral pointer to a HEAD. Such pointers are implemented in Mercurial as bookmarks.
If the unwanted branches appear on commits which are (ancestors of) commits you want to publish, there is very little you can do, short of recreating the history with all-new hashes. This could (for instance) be done with hg export and hg import, along with local cloning and (probably) a certain amount of shell scripting. More efficiently, you could use the convert extension to automate the process. Since this changes commit hashes, it will likely cause serious problems if any of the commits have already been distributed publicly.
If you have no interest in sharing the offending commits, you can simply not publish them. This can be done with selective pushing. However, since you'll always have to manually exclude those commits every time you push, it's probably safer to clone and strip (or clone selectively with the -r flag). You can then push from your partial clone with impunity. Assuming you have a sufficiently recent version of Mercurial, you can also force the commits into the secret phase, so that they will not be pushed:
hg phase -fs revisions
You don't want to use hg strip, because it permanently removes the commits from the history (see Editing History in the Mercurial wiki)
If I were you, I would close the branches instead:
hg up -C badbranch
hg commit --close-branch -m 'close badbranch, this approach never worked'
hg up -C default
(source: Pruning branches in the Mercurial wiki)
After closing a branch, hg branches doesn't show it anymore.
If you do want to see closed branches, use the -c parameter:
hg branches -c
Disadvantage:
hg his still shows closed branches.
You could use the -b parameter though, to show only the default branch:
hg his -b default
I am newbie dealing with mercurial. I did some mess trying on branches and now I want to "flat" all branches in just one "default"
josir#josir-desktop:~/bitbucket/campus$ hg branches
default 27:f28e8d8773c6
15 20:6b434f251b7e
branches has already been pushed to remote repo.
I want to purge all other branches discarding all changes on it. Reading those tutorial, I could not identify the best option to fix it.
The easiest thing is to just "close" the unwanted branches and leave them in peace:
hg update -r "branch('15')"
...
hg commit --close-branch
If you only have push/pull access to the remote repo, there's no way to remove changesets after you've pushed them. So close the branch and move on, or discard the bitbucket repo, clean the local one, and start over.
To clean up your local repo, if you have a big mess the easiest way is to pick a good revision (e.g., the tip of default, but you can choose an earlier one) and clone just that and all its ancestors:
hg clone -r <goodrev> messy-repo new-repo
The documentation (which you'd already cited) has a good explanation of this and several other branch-pruning options, but none of them are appropriate after you've pushed to a repository you don't control.
For already pushed branch you haven't any freedom: only --close-branch
When I issue hg branches, I got a two column report like the above:
josir#josir-desktop:~/bitbucket/spo$ hg branches
dev 232:31cf2690dd47 (inativo)
What have I understood for that ?
There are 2 opened branches :(
That was my big mistake. There is just ONE branch: dev
The second column "232:31cf..." is just the last commit of the "dev" branch!!!
I'm new to Mercurial, and I made the mistake of making different changes on different systems before the main repository was up to date. (I understand this is what Mercurial is built for, but my thick brain is struggling to resolve the issue.)
Now on my primary development server, everything is up to date and committed. However...
$ hg push
abort: push creates new remote branches: 4f2672f039d7!
(use 'hg push --new-branch' to create new remote branches)
I don't really want a new branch. I just want all the changes to be merged.
$ hg heads
changeset: 459:ff5f94e44aba
branch: 4f2672f039d7
tag: tip
parent: 458:e63d02baf4cf
parent: 455:267abda62069
user: mike#...
date: Tue Sep 13 14:25:16 2011 -0400
summary: Images from prof
changeset: 455:267abda62069
parent: 453:a74757e26357
user: mike#localhost.localdomain
date: Tue Sep 13 09:08:12 2011 -0400
summary: images for FLC
Point me in the right direction?
EDIT: (adding detail)
When I try to merge, I get the following result:
$ hg merge
abort: branch '4f2672f039d7' has one head - please merge with an explicit rev
(run 'hg heads' to see all heads)
I have tried hg merge ff5f94e44aba, and all of the revs listed above, and each one returns the same result:
$ hg merge 267abda62069
abort: merging with a working directory ancestor has no effect
It looks like you've accidentally created a branch with a silly name. What you most likely want to do is reapply your changes with a branch name that makes better sense. There's no totally automatic way of doing this, but you can extract each changeset as a patch, revert to the point where you messed up and reapply those changes on the proper branch.
Basically what you need to do is look at the changelog; probably by running hg out to see what's missing from the central repository. Make a note of each of the revs that you want to keep.
Next update to the last good revision. Make sure that you are on the branch you wanted your commits to be on.
Now you will apply each of the changes you made and commit each one. You can automate this process something like this:
BADREVS="123 124 125 126"
recommit() { hg di -c $1 | patch -p1; hg ci -m "$(hg log -r $1 --template '{desc}')";}
for rev in $BADREVS; do
recommit $rev
done
Now you've got your changes in your local repository twice; once as the commits on the weird branch and again on the right branch. You can push those changes to the central repo using hg push -b GOODBRANCH so that only the changes to the right branch go up; Alternatively, you can install the strip extension to remove the changes you didn't want from the local repo and then you can push as normal.
By the sound of it; you will still have to deal with the changes made to the central repository before you can push, since you pushed changes from another repo. You probably want to do this merging after you clean up the change history in the local repo.
Pull from remote and then update / merge / commit first. Then you won't make new branches.
I've had this happen when I missed a merge. I like the TortoiseHg workbench for this because it can be a little easier to find what you missed through visualization.
A good way to avoid this in the future, how I stopped getting this error, is the fetch extension. Set your post pull to fetch and it will automatically merge for you, which is very nice. If there's a conflict it brings up whatever conflict resolver you use.
branching out -
[default]$ hg branch talks
[talks]$ <... some commits ...>
[talks]$ hg update default
merging back -
[default]$ hg merge talks
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
pushing to remote repo -
[default]$ hg commit -m "merging talks to default"
[default]$ $ hg push
abort: push creates new remote branches: talks!
(use 'hg push --new-branch' to create new remote branches)
Further investigation revealed that remote repo doesn't want me to have multiple heads at the remote end. But I just did a merge to merge the two heads into one, isn't it?
The graph from hg serve also seems to agree with me (I hope)
However, I also see two heads from hg heads
[default]$ hg branches
default 9:85752ecd6326
talks 8:2b00714d76d5 (inactive)
The solution is in the abort message: use 'hg push --new-branch'. You've created a named branch called talks so it needs this extra switch, regardless if you have merged the named branch back to default.
I'm guessing you've misunderstood the branch feature. You've just created a branch who's name will live forever in the repository. I suspect you didn't really want to do this. You might want to investigate the bookmarks feature for local branches that don't end up with names that live forever in the repository.
Mercurial balks at pushes that add new global branch names to the repository being pushed to because that's so very rarely what you really want to do. hg push --new-branch will tell Mercurial that yes, you really mean to do that.
The two heads you're seeing are misleading. Notice how one head is listed as '(inactive)'. That just means it's the last change on the global branch, but not an actual head. You frequently want to see the heads of branches, even if those heads actually have children and are not really heads.
As a small aside... I wrote the code that added that feature to the 'heads' command awhile back. :-)
Currently my company is using cvs for version control. We have an old branch of code which has been used specifically for one client (don't ask) that we'd like to merge to the head.
Due to the delta between this branch and the head I think the merging capabilities of mercurial should make my job a bit easier. My line of reasoning is:
Create mercurial repositories of the branch and the current head.
Do a merge of the branch repo to the trunk repo.
At this stage I'm expecting mercurial to provide better merge support than cvs.
Then I would commit my changes to the trunk repository back into cvs.
Is this approach sound? Will this strategy result in a less painful merge as I think it will, or is there something I'm missing?
The reason Mercurial merges better than CVS or Subversion is because it tracks the most recent common ancestor of the two heads/branches, so you'll to make sure you're providing that information accurately or you'll probably end up with a worse merge.
If you do something like this:
hg init newrepo
cd newrepo
cvs checkout POINT_OF_DIVERGENCE
hg commit --addremove -m 'commiting point of divergence'
cvs checkout BRANCH
hg addremove --similarity 90 # let Mercurial discover any renames
hg commit -m 'committing branch head'
hg update -r 0 # jump back to point of divergence
cvs checkout HEAD
hg addremove --similarity 90 # let Mercurial discover any renames
hg commit -m 'commiting HEAD head'
hg merge
then the common ancestor for the two heads will be the point of divergence (sorry if the CVS commands are wrong, it's been a mercifully long time).
The trouble is knowing where the POINT_OF_DIVERGENCE is in the CVS repo -- CVS doesn't keep track of that at all, which is why its own merge doesn't use it.
CVS best practices always suggest that whenever you branch you create a tag that marks the point of divergence, but if you didn't do that then there's some tricky hunting ahead of you.
Without a correct most recent common ancestor the Mercurial merge won't be any better than CVS's.
Yes, that should work but there might be tiny little problems along the way (like how to get the source from CVS into Mercurial: Using hg convert or doing a manual import of a certain revision, etc).
Please create a new question if you run into a problem.
The built-in convert extension won't do well with CVS except for very simple histories. Use the fork of cvs2svn called cvs2hg
http://hg.gerg.ca/cvs2svn