Mercurial: pull changes from unversioned copy - version-control

I am currently maintaining a Mercurial repository of the project I am working on.
The rest of the team, however, doesn't.
There is a "good" (unversioned) copy of the code base that I can access by SSH. What I would like to do is be able to do something like an hg pull from that good copy into my master repository whenever it gets updated.
As far as I can tell, there's no obvious way to do this, as hg pull requires you have a source hg repository.
I suppose I could use a utility like rsync to update my repository, then commit, but I was wondering:
Is there was an easier/less contrived way to do this?

In short: not that I know of.
If I were in your position, though, I'd keep the "central" code in one branch, do my dev in another branch, then have scripts which would push/pull as appropriate.
For example, the pull script would:
hg co central (making sure to abort if the working copy had uncommitted changes)
rsync ssh://central/repo
hg ci -m "snapshot of central on $(date)"
The push script would then be something like:
./pull
hg co central
hg merge <your working branch>
... test, fix any conflicts ...
rsync . ssh://central/repo
Finally, I would apply clue stick liberally until the rest of the team is on board :) (although you probably knew that already).

Related

What commands do you use to refresh your development environment with Mercurial?

I guess I'm learning somewhat backwards. I'm very comfortable with git and never used mercurial until my most recent project.
One of the things that bothers me is that sometimes I can't seem to refresh my development environment because of un-tracked file errors. I really don't care whether files are tracked/untracked on the development server. I'd just like to be able to pull the most recent state of the repo from bitbucket.
Unfortunately, I sometimes end up resorting to nuking the app and re-cloning. Normally this wouldn't be that big of a deal but there are dependencies that I need to add back to the app each time I do this because they are not stored in the repo.
With git I would run...
git reset --hard; git checkout master -f; git pull; git checkout origin/master -f
What's the mercurial equivalent? I've tried...
hg revert --all; hg pull; hg update;
Which seems to work as I would expect it sometimes. When it doesn't work it aborts due to the untracked file errors. I'm looking for something that works all the time.
hg up --clean
That's all there is to it. (hg up rather than hg update because hg is cooler than git and allows unique abbreviations. I dislike the way when I'm forced to use git it doesn't accept git ci like a sane version control system. I know I could make an alias... but I haven't ever got round to it partially as I don't use it very often at all)
hg help [command] (or hg [command] --help) is useful. The help for revert mentions that you probably want to use hg update -r rev or hg update --clean . instead.
This will only change tracked files. Untracked files will be left alone, which I think is what you want.

Is 'pull' a synonym for 'clone' in a Mercurial source-control repository?

I'm seeing the command 'pull' and wondering how that's different from a 'clone'. Both terms seem to imply retrieving code from some remote repository. Is there some subtle distinction here?
Use clone when you need to make a new repository based on another. Use pull later to transfer new changesets into the clone. You cannot use clone to fetch just the newest changesets — that is what pull is for. The pull command will compare the two repositories, find the missing changesets in your repository and finally transfer those.
However, you are right that there are similarities between clone and pull: they both transfer history between repositories. If you clone first
hg clone https://www.mercurial-scm.org/repo/hg/
then this has the exact same effect as doing
hg init hg
cd hg
hg pull https://www.mercurial-scm.org/repo/hg/
hg update
You get the exact same history in both cases. The clone command is more convenient, though, since it also edits the .hg/hgrc file for you to setup the default path:
[paths]
default = https://www.mercurial-scm.org/repo/hg/
This is what lets you do hg pull in the repository without specifying a URL. Another advantage of using clone is when you work with repositories on the same disk: hg clone a b will be very fast and cheap in terms of disk space since b will share the history with a. This is done using hardlinks and works on all platforms (Windows, Linux, Mac).
hg clone is how you make a local copy of a remote repository. The Subversion equivalent is svn checkout.
hg pull pulls changes from another repository. hg update applies those changes to the local repository. hg pull -u is equivalent to hg pull; hg update. The Subversion equivalent to hg pull -u is svn update.
clone creates a new repository as a copy of an existing repository.
pull imports all changesets (not already present) from another repository into an existing repository.

Merge two checkouts in bazaar

I'm just starting out with bazaar, and I've found that the checkout feature is the most useful for the way I work - namely I can c/o from a "master copy", do some development and then commit my changes in the new directory. This then updates the "master copy".
But what if I'm working on (eg) two projects, changing different portions of code? Say:
~/master - master copy
bzr co master ./gui
bzr co master ./engine
So I'm doing gui-related stuff in the ./gui directory and under-the-hood stuff in ./engine. How should I commit my changes? If I commit gui first, then engine, I guess any conflicts will be flagged in engine?
Is there a way to merge gui and engine, and then do just one commit to the master copy?
To make things a little more complicated, how about if I do this:
bzr branch gui ./mouse
Now I perhaps I've been working on mouse, but also on gui. If I want to merge the code from gui AND mouse, and then commit to master, what is the best way to manage this? Or indeed, if I also:
bzr branch gui ./keyboard
If I've changed altered gui, keyboard and mouse, should I hierarchically merge - ie mouse+keyboard, then merge this with gui, then commit gui to master?
I hope it is clear what I'm trying to achieve! Thanks in advance for your time.
If you have two checkouts, any time you commit changes to one, you will first have to pull down any changes from the other one, potentially having to resolve conflicts at each step. This is generally a good idea, since it's easier to resolve conflicts over time and make sure your code doesn't diverge too much.
However, it sounds like you want to have separate developers working on "gui" and "engine", or you just want to save your conflict resolution till development on both branches has completed. In this case, you should probably create them as independent branches with "bzr branch". Each branch can use local commits and not worry about conflicts with each other. Then when it comes time to merge you can do it one of 3 ways, all of which get the same end result:
1. Merge one branch into the other, then push it up to master:
cd gui
bzr merge ../engine
# manually fix any conflicts
bzr commit
bzr push #back up to main
The downside to the above method is that your "gui" branch now has the "engine" changes in it. Which is fine if you're going to throw away both branches once they're pushed back into the mainline. But if you want to keep the branches longer, you can:
2. Merge into the mainline:
cd master
bzr merge ../gui
bzr commit
bzr merge ../engine
# manually fix conflicts
bzr commit
This has the upside that you still have "gui" and "engine" as separate branches, but you've had to commit one to master before you were sure that they would both work together. So you really probably want to:
3. Create a merge branch:
bzr branch ~/master gui-engine-merge
cd gui-engine-merge
bzr merge ../gui
bzr commit
bzr merge ../engine
# manually fix conflicts
bzr commit
bzr push ~/master
# since this branch was only for merging, you don't need it anymore:
cd ..
rm -r gui-engine-merge
Yes, bzr should prevent you from checking in changes from the engine repo if it detects conflicts. Normally, you first do "bzr up" just prior to check-in and then make sure your stuff plays nice with others.
As for the second part of your question, dealing with mouse/keyboard branches, this is how I would normally do it. Simply cd into the gui dir, and then do:
bzr merge ../mouse
After merging the changes, you can then commit from the gui directory and it will send the changeset to the "master" directory.
Note that I'm hardly a bzr expert, but this is the way I've been dealing with SVN repos.

Fastest way to "reset" Mercurial repository to Version X (without cloning)

Let's say I clone a remote Mercurial repository (over the local network or even over the Internet) to try something out.
I work in my clone, make a few commits...and then I realize that my changes don't make sense and I have to start over again.
So I want to have a "fresh" clone again, from the same source repository.
Basically, I want to "reset" my local repo to the point before I started experimenting.
What's the best / fastest way to do this?
The simplest way would be to just make a new clone, but then HG copies the whole repo and the whole history over the network again.
If the repo is really big, this will take some time and/or block the network.
I tried to make a new clone into the same folder (hoping that HG would recognize this and update only the files which have changed and the history) but that seems to copy the whole repo as well.
I could "hg rollback", but this rollbacks only the last commit. If I made several commits, I can only undo the last one. So I can't reset the repo to the point before I started committing.
Any ideas?
Is there really no other way than to clone the whole thing again?
(note: a solution with TortoiseHg would be nice...I prefer this over the command line)
You'll end us using hg strip as gizmo suggests, but the traditional way to do this would be to clone again -- not from the remote repo, but from your own local repo. For example, if you checkout is 'repository' and you've added changesets 99 and 100 that you don't like you'd do:
cd ..
hg clone -r 98 respository repository-scrubbed
mv repository respository-with-crap-I-do-not-want
mv repository-scrubbed repository
That should be near instantaneous.
If you enable the Strip Extension, you can use the "hg strip" command that will remove the history you don't want anymore.
More information is available on the Strip command wiki page.
hg update -r <changeset number>
eg hg update -r 1 for the second version. You can use hg log to see what version you want

How do I send a patch to another developer and avoid merge conflicts?

How do I get a patch from a commit in order to send it to another developer? And how do I best avoid a merge conflict with this patch when merging our trees at a later date?
If you know how please explain how to do this in your VCS of choice such as subversion, git, Mercurial, bzr or etc.
In git you can pipe the output of git-diff between two commits like this:
git diff fa1afe1 deadbeef > patch.diff
Send the patch.diff to the developer and let him git-apply it to his workspace like this:
git apply patch.diff
If the other developer already has the commits available in his repository he could always pipe it in himself without merging like this:
git apply < git diff fa1afe1 deadbeef
You can then add and commit the changes in the diff the usual way.
Now here comes the interesting part when you have to merge the patch back to the master branch (that is public). Consider the following revision tree where C* is the applied patch from C in the master branch:
A---B---C---D master, public/master
\
E---C*---F feature_foo
You can use git-rebase to update the topic branch (in this example named feature_foo) with it's upstream head. What that means is when you type in the following:
git rebase master feature_foo
Git will rearrange the revision tree like this and will also apply the patch itself:
A---B---C---D master, public/master
\
E*---F* feature_foo
Merging to the upstream branch will now be an easy fast-forward merge. Also check that the new commits E* and F* work as the previous E and F respectively.
You can do the same thing against another developer's branch using the same steps but instead of doing it on a public repo, you'll be fetching revisions from the developer's repository. This way you won't have to ask the other developer for a patch if it is already available from what he published at his repo.
Please note to never rebase a public branch because the command will rewrite git history which is something you don't want to do on branches that people depend on and will create a mess when merging to remote repositories. Also never forget to integrate often so others in your team can take part of your changes.
In SVN you can simply make your changes then before commiting, pipe the output of the svn diff to a file as such
svn diff > mypatch.diff
you can then revert your changes and apply the patch at a later date using
patch -p0 -i mypatch.diff
As always don't blindly apply patches to your code and always inspect them first.
You may also find that the patch will break your source code if the source files have changed significantly enough since the patch was taken.
You also can not guarantee that there will not be merge conflicts when you attempt to check in the code.
Bzr handles sending a "merge directive", meaning it sends the patch for you so that the other party can simply click "OK" to merge and there's less futzing around with patch/apply etc.
just:
$ bzr send -o mycode.patch
In Subversion there is no nice way of doing this. Yes, you can use svn diff + patch but this will only postpone your problems until you are going to merge and by then chances are that you've forgotten about it.
The way you would do it in Subversion would be to create a branch, do the commit on the branch and ask the recipient of the patch to switch to the branch. Then you can merge the branch back to trunk in the usual way.