We're using Mercurial where I work and I want to have a setup similar to how I used SVN:
Trunk
Tags
Production
Branches
Since Mercurial supports branches natively, I know how to create a named branch, but I can't find any documentation on how to repeatedly merge 'Trunk' with 'Production'.
Quite simply, I want to have a development branch for normal work and a production branch that I routinely pull changes from the development branch into. How do I do this with Mercurial?
As the previous poster mentioned, the transplant extension can be used for cherry-picking individual changes from one branch to another. If, however, you always want to pull all the latest changes, the hg merge command will get you there.
The simplest case is when you're using clones to implement branching (since that's the use case Mercurial is designed around). Assuming you've turned on the built-in fetch extension in your .hgrc / Mercurial.ini:
cd ~/src/development
# hack hack hack
hg commit -m "Made some changes"
cd ../production
hg fetch ../development
If you're using local branches:
hg update -C development
# hack hack hack
hg commit -m "Made some changes"
hg update -C production
hg merge development
hg commit -m "Merged from development"
Something like hg transplant? That's what we use on our dev and prod branches.
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 have two Mercurial repositories that are for different major revisions of the same project. The latter version is a massive change to the functionality, and especially the UI, of the project, but it will still have a lot of common code with the earlier version. (For shorthand I'll call these versions 4.6 and 5.0 and the repositories project-4.x and project-5.x going forward; that's basically what I'm dealing with.)[1]
As we thought more carefully about the structure of our repository, and thinking especially about how to handle the related code, it became apparent that we wanted to simply pull the repositories together and used named branches for the ongoing work in each (from which people can branch or bookmark and merge as necessary). To do that, we decided we basically need to pull the project-5.x repository into the project-4.x repository. From what I can see, combining the repositories should be fairly straightforward:
$ hg pull -f project-5.x # in project-4.x
$ hg merge
So far, so good. My concern is handling the branching issue.[2] These are going to come in as two completely unrelated chains (which is fine), but I'd like the branch structure to look something like this:
---4.6----- }
\ } original project-4.x
5.0----- }
/
------- } original project-5.x
The problem is, I'm not exactly sure how to do it.
Edit: See below; the answer I devised worked.
Footnotes
If you're wondering why this is only coming up now… well, the project only got version controlled as of starting 4.6. Which, yes, is a little bit crazy. And I'd never been in charge of a major version change like this before, so I decided originally to make a new repo entirely, which I of course now regret. Live and learn.
Answers I've already read on the subject (but which left me unsure how to do this exactly):
Mercurial - merging branches
How do I merge two Mercurial repos into a single one
How can I import a mercurial repo (including history) into another mercurial repo as a subdirectory, without using subrepos?
I originally thought I'd need some way to pull into just the branch, but after chewing on it some more, I concluded the best way to do this is roughly as follows:
Create the desired new branch structure (i.e. create the 4.6 and 5.0 branches).
Remove the old default branch into the 4.6 branch in the base repository.
Pull the project-5.x repository into the project-4.x repository.
Merge the default (or in the case of this repository, experimental) baseline, which is pulled in during the merge, into the 5.0 branch, closing out the experimental branch along the way.
Restrict write access to the old repository's central push/pull location; we still have it for historical reasons, but people can't accidentally push to it.
Preparation (steps 1–2)
$ cd <project-4.x directory>
$ hg branch 4.6
$ hg ci -m "New 4.0 baseline"
$ hg branch 5.0
$ hg ci -m "New 5.0 baseline"
$ hg up default
$ hg ci --close-branch -m "Close default branch going forward.
$ hg up 4.6
$ hg merge default
$ hg ci -m "branch merge default -> 4.6"
At this point, the repository is set up: it has the new baseline branches and has removed the old default branch we wanted to get rid of.
After this, I made the changes to get the repository structure looking more the way it needed to for the 5.0 branch in the project-4.x repository (since massive restructuring is part of the version change effort).
Repository merge (steps 3–4)
The next step was actually merging the repositories together and pushing the content from the old repository into the desired branch.
$ hg pull -f <path to project-5.x repository> # still in project-4.x repository
$ hg merge -m "Merge in project-5.x repository"
$ hg up experimental # experimental is the name of the "default" branch
$ hg ci --close-branch -m "Close experimental branch"
$ hg up 5.0
$ hg merge experimental
$ hg ci -m "Merge old experimental into new 5.0 baseline"
This proceeded perfectly, with no merge conflicts whatsoever (except that I needed to resolve some small differences in my .hgignore file).
I have a Mercurial repo at Bitbucket and on my local machine, both are mirrors, up to date. I created a feature branch, reflected in both repos. I did all my work in the feature branch.
The feature branch is now complete and I want to now make it the default for the main repo and my local copy. I don't really care about the default branch, enough work has gone into the feature branch that all I want to do is designate it as the new default.
I don't think I want to merge nor should I? How can I do this so both local and remote don't get confused?
Just merge feature-branch into default then close feature-branch:
$ hg checkout default
$ hg merge feature-branch
$ hg commit
$ hg checkout feature-branch
$ hg commit --close-branch
There is no more clean and sensible way (that I'm aware of) to “make feature-branch the default”.
One thing that wouldn't be as nice, but you could do, is to make a commit to default on top of feature-branch:
$ hg checkout feature-branch
$ hg branch default
$ hg commit
But this would leave two heads in the default branch, which is suboptimal.
Since Mercurial 2.4, you can create an bookmark called # and Mercurial will checkout that revision new clones.
However, I would still try to stick with using default as the branch where the main development takes place. Doing so will cause the least amount of surprise for developers already used to Mercurial — the wiki describes the standard way to use branches in Mercurial.
If you follow the conventional advice of using default as the main branch for development, then you should close your feature branch before you merge it back:
$ hg update feature-branch
$ hg commit --close-branch -m "Feature done, merging into default branch"
$ hg update default
$ hg merge feature-branch
$ hg commit
If you haven't done any work at all on the default branch since your started the feature branch, then this merge will be trivial and have no conflicts. Otherwise you'll have to resolve conflicts. If you're sure you want to keep everything from the feature branch, then you can do
$ hg merge --noninteractive --tool internal:local feature-branch
$ hg revert --all --rev feature-branch
instead of just hg merge above. That will make sure that the new commit on default look exactly like the last commit on feature-branch.
I succeded without merging by closing the default branch.
in my development repository working directory:
$ hg update default
$ hg commit --close
then my development branch became the new default branch.
But i do not know the rules for why my development branch was choosen
as the new default.
i think it is because it was my tip ?
(or maybe last changed branch? (tip?))
I also think that you have to repeat that next time.
Because i think my chosen branch name was "overwritten" by the 'default' name.
It would be nice to have branch name.
dev-projectname-version.x=default
regards
I wanted to do just what you described and hunted around until I found an answer which uses the revert command to do just what you describe. Here is the code I used:
hg revert --all --rev ${1}
hg commit -m "Restoring branch ${1} as default"
where ${1} is the number of the revision or the name of the branch. These two lines are actually part of a bash script, but they work fine on their own if you want to do it manually.
This is useful if you need to add a hot fix to a release branch, but need to build from default (until we get our CI tools right and able to build from branches and later do away with release branches as well).
The main repository is where all the developers check-in, lets says its located at
http://hg.main.com:8000/project
Now, we also have http://hg.qa.com:8000/project where all the LATEST code need to be in Sync, PLUS the tests and other artifacts are in this repository. which will ONLY be "pushed" to central repository if 85% of the tests will PASS.
Is there a better way to implement this?
What hg commands would i need, to make sure that i dont overwrite latest commits
start with something ilke:
Approval Management: Auditing and QA
For whom?
If you need explicitely approved code history with a full track record using a team of developers and a seperate QA team, this workflow might be right for you.
Requirements
You need just Mercurial (command line), a shared repository for exchanging data (a simple SSH-server suffices, as does a single private bitbucket repository) and the GpgExtension.
Flow
This workflow uses the default branch for development, as well as a QA named branch and a release branch.
The advantage is that merging default into QA requires an explicit merge which can subsequently be GPG signed by the developer responsible for it.
When QA finishes applying their changes, they first of all merge back into default (so that developers work on the QA version) and then merge into release, GPG signing the merge commit.
Developer
hg pull # get the latest changes
hg update
hg commit -m ""
hg update -C QA
hg merge default
hg commit -m "merged default branch for QA"
hg sign
hg push
QA
hg pull
hg update QA
hg commit -m "QA fixes"
hg update -C default
hg merge QA
hg ci -m "merged QA fixes back into the development branch"
hg update -C release
hg merge QA
hg commit -m "merged finished QA into release"
hg sign
Modifications
If you need more layers than just developers and QA, just add additional named branches, for example staging-release before release.
To make sure that the code has really been checked by all, you can require that all heads must be GnuPG signed in order to enter a higher-up repository.
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