bitbucket, "hg push" and "hg update" - mercurial

If I start out with a local mercurial repo, which I consider to be the "main" repo (pardon me my dvcs lords), and intend to use bitbucket as a backup and issue tracking facility, I can do all my changes in my local repo and do an "hg push" to send the changes back to bitbucket.
Don't I need to follow this "hg push" command run on my local machine with an "hg update"?

Why do you care what's in the working directory on BitBucket's servers? As long as you push the changes will be in the repository and visible on the BitBucket page.
EDIT: OK, I'm going to edit this to be a useful answer.
Say you clone down one of my repositories like django-hoptoad on BitBucket. You'll have a folder named django-hoptoad on your local machine and its content will look something like this:
django-hoptoad/
|
+-- .hg/
|
+-- ... my code and other folders
All the data about the repository itself is stored in the .hg/ folder. That's where Mercurial keeps the data about which files were changed in which changesets, and lots of other stuff.
You can think of it like this (though it's an oversimplification):
django-hoptoad/
|
+-- .hg/
| |
| +-- data about changeset 1
| +-- data about changeset 2
|
+-- ... my code and other folders as they appear in changeset 2
When you run hg pull and don't update, you pull any new changesets into the repository:
django-hoptoad/
|
+-- .hg/
| |
| +-- data about changeset 1
| +-- data about changeset 2
| +-- data about changeset 3 (NEW)
| +-- data about changeset 4 (NEW)
|
+-- ... my code and other folders as they appear in changeset 2
If you don't update, the ... my code and other folders will still be equivalent to whatever is in changeset 2, but the other changesets are still in the repository.
When you run hg update Mercurial will update the ... my code and other folders to the contents of the newest changeset.
django-hoptoad/
|
+-- .hg/
| |
| +-- data about changeset 1
| +-- data about changeset 2
| +-- data about changeset 3
| +-- data about changeset 4
|
+-- ... my code and other folders as they appear in changeset 4
Really, this means that what happens to be in ... my code and other folders doesn't have to match what's in the repository. You could just delete it and all the changesets would still be in the repository:
django-hoptoad/
|
+-- .hg/
|
+-- data about changeset 1
+-- data about changeset 2
+-- data about changeset 3
+-- data about changeset 4
If you committed right now, it would create a new changeset that basically says "no files". You don't have to commit though. People can still push and pull from you because the repository still has all the data about the changesets.
This is almost certainly what BitBucket is doing. You're never going to log in to BitBucket's servers, edit your code and commit there -- you're only ever going to push/pull/clone. That means the ... my code and other folders will never actually be used, so I'd imagine Jesper has it set up to delete it to save the disk space.
Since hg update only really affects the working directory, and the working directory on BitBucket is never used, you don't need to run hg update after you push to BitBucket.

I think you might be getting confused between the working copy (aka working directory) and the local repository. These are related but separate things. The local repository contains the full history of all tracked files whereas the working copy contains versions of the files from a particular revision plus your changes to them,
The hg command push and pull move changes between repositories and update and commit moves changes between your working copy and your local repository.
So if you push changes to a remote repository that will not change the local repository and so there's no need to run an update on the local repository. However, anyone using the remote repository will need to do an update so your changes are shown in their working copy. Conversely, if you pull changes from a remote repository you will need to do an update so that these changes are shown in your working copy.
Similarly, you need to commit all changes from your working copy into the local repository before they can be sent to another repository using push.

Bitbucket shows you the repository. As pointed out by Dave Webb, hg update is concerned with updating the working copy. When you do hg push you are transferring changesets in order to update the repository on Bitbucket -- and so the webinterface will show this.
There are no working copies on Bitbucket, as pointed out by Steve Losh. There is also no hg update being done behind your back.
You can experiment with this yourself by making a clone without a working copy:
% hg clone --noupdate repo repo-empty
then go into repo-empty and do hg log. You will see that even though there are no files there, the history (i.e., the repository) has still been cloned. You can make the files appear with the hg update command:
% hg update
and disappear again with
% hg update null
The working copy is only needed if you want to look at the files and make new commits. Otherwise you can remove it to save space. This is normally done in clones that are only used for serving with hg serve or the equivalent thing that Bitbucket uses.

No need to do a hg update on your local machine. Update is used when data is pushed TO your local repository, and you are pushing FROM your local repository.

Related

Mercurial update doesn't work for subrepo if subrepo belongs to two main repos?

Take this repo structure:
Server (main repo)
ProjectA (subrepo)
SharedLibrary (subrepo)
Client (main repo)
ProjectB (subrepo)
SharedLibrary (subrepo)
SharedLibrary points to the same folder (this is Windows), it is not a separate copy/clone under each main repo.
Assume each main repo has two changesets, 0 and 1(tip). We start with both main repos at the 1(tip) revision.
Take the following steps:
In the Client repo, update to changeset 0. This updates ProjectB and SharedLibrary to earlier but matching revisions.
ProjectA is now out of sync with SharedLibrary. Step 1 updated SharedLibrary to an older revision than what is required for ProjectA, which is still at 1(tip).
In the Server repo, we want to update SharedLibrary to the correct revision for ProjectA, so we run hg update tip in the Server main repo. This does NOT update SharedLibrary to the correct revision. It leaves SharedLibrary in the same revision as step one.
Go back to Client repo and run hg update tip. SharedLibrary is now at the correct revision for both ProjectA and ProjectB.
It appears updating in the Server repo isn't checking to see if SharedLibrary is at the correct revision. Is this behavior expected, or is there a better way to do this?
What you're seeing is that hg update will merge when the working copy is dirty. Let me explain it with a normal file first. Imagine you have a repository with two revisions. I'm at revision 0 and foo is modified:
$ hg diff
diff --git a/foo b/foo
--- a/foo
+++ b/foo
## -1,3 +1,3 ##
first
second
-third
+third line
You see I changed the third line. Now, if I run hg update 1 the modification will be merged with how foo looks like in revision 1:
$ hg update 1
merging foo
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
The modification is still there and foo is still dirty:
$ hg diff
diff --git a/foo b/foo
--- a/foo
+++ b/foo
## -1,3 +1,3 ##
first line
second
-third
+third line
When you did
$ cd client
$ hg update 0
you made sure that SharedLibrary was updated to the revision described in .hgsubstate for revision 0 in client.
When you then went to server, the SharedLibrary subrepo was no longer at the revision mentioned in .hgsubstate at revision 1 in server. In other words, the working copy in server was dirty — a hg commit would result in a new .hgsubstate file being committed.
Mercurial preserves this modification when you hg update in server and this is why you see that SharedLibrary wasn't made current when you updated. Use hg update -C if you want to make the subrepo current.
The idea behind this feature is that you can test different versions of your subrepos. When hunting for a bug, it's often necessary to update the main repository to older versions and so it's convenient that the modifications to the subrepo revisions stay in place.
Note that the confusing situation you're seeing isn't caused by how you've re-used the same subrepo twice. However, as Lasse points out, the real way to use a single subrepo in multiple projects is to put it once on your server and then clone it into your local clones — once per clone.
I've described this in more detail, but briefly you should follow the recommendations and maintain an identical structure on both server and clients. Use SharedLibrary = SharedLibrary paths in your .hgsub file to maintain this structure. Link the repositories together on the server-side (see my other answer) to make a single repository appear under several different URLs/directories.
When starting out with subrepos, then beware of tight coupling. If you can, then try to use a proper dependency management system such as Maven+Nexus for Java based projects.

Mercurial: get fresh copy

I have a local repository and I want to get the latest changes from a remote repository. I know i can clone but clone only works on new directories. I know i can delete the local repository and then clone but i want to know how do it the Mercurial way if there is one.
EDIT: hg pull -u doesn't work if there are conflicts. I don't want to resolve conflicts I just want to get a fresh copy of the remote repo regardless of local changes.
ANSWER: Short answer: Maybe it can be done (see answer below) but re-clone is easier.
Long answer: if you want to get the latest from a remote and disregard your local changes and commits then you'll have to clone to a new local repository or remove the local repository and clone another one. This is because if you have conflicting changes then hg will force you to resolve them manually.
Which is OK but I just wanted to know if it can be done without removing my local repo.
I think you're just looking for this:
hg pull
hg up --clean
That will pull latest set of revisions from the remote repoistory and then update your local repository with a clean copy, regardless of whether or not you have made any changes to the files. No merging necessary.
The only caveat is, if you have added files to your local repository, and they have not been committed, they will be orphaned (left in place, but not in the repository) after the update. If you do an hg stat you should see them denoted with question marks. If the added files have been committed to your local repository, Mercurial will properly clean up after them.
Here's the remote repository (remote rev 6):
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 3/24/2011 2:16 PM .hg
-a--- 3/24/2011 2:16 PM 83 addedtoremote.txt
-a--- 3/24/2011 1:56 PM 726 sample.txt
Here's the local repository (cloned from remote rev 4 earlier) with changed and added files (local rev 5):
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 3/24/2011 2:03 PM .hg
-a--- 3/24/2011 2:05 PM 9 sample.txt
-a--- 3/24/2011 2:05 PM 58 addedtolocal.txt
Here's the local repository after doing a pull and clean update (local rev 6):
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 3/24/2011 2:17 PM .hg
-a--- 3/24/2011 2:17 PM 83 addedtoremote.txt
-a--- 3/24/2011 2:15 PM 726 sample.txt
The changes to sample.txt have been wiped out, addedtolocal.txt has been deleted and addedtoremote.txt has been added.
Looks like you are looking for hg strip, which isn't part of the Mercurial core. It's available through the MqExtension. You can enable it by adding the following in your .hgrc or Mercurial.ini file (https://www.mercurial-scm.org/wiki/MqExtension)
[extensions]
mq =
Then you will be able to:
hg strip rev
This will remove your changesets to the point where you shouldn't have any merge conflicts. This will impact the branch history though. But then again, that's not so bad, if you keep them any good future changeset will have an ancestor that you decided to trash.
If you are just trying something out, you're better of doing it in a separate branch which is easy to close and abandon later.
If you really are looking to keep the bad changeset you can pass in configuration option to the merge command like this
hg --config ui.merge=internal:other merge
This is documented in Mercurial tips and tricks.
Just "pull" changes from the remote repo. Think that "pull" and "push" are change-sets transactions between repos.
Once done, you have to "update" the sources.
You can rebase your modifications, minimizing the need for merges. Just call hg pull --rebase
You'll have to have rebase extension enabled in your ~/.hgrc:
[extensions]
rebase =
Since this is such a common action, there is an extension that does a hg pull -u, hg merge and hg commit in one command:
hg fetch
From the hg book:
Enabling the fetch extension is easy.
Edit the .hgrc file in your home
directory, and either go to the
extensions section or create an
extensions section. Then add a line
that simply reads “fetch=”.
[extensions]
fetch =

How do I extend a mercurial repository to include parent folder?

Now, I have a source tree as following:
+ Dev
+-- Source
| +-- ...
+-- Samples
| +-- ...
+-- ...
Beginning, I had create a Mercurial repository in folder "Dev/Source". It's work fine. But now, I want extend the repository to include "Dev/Samples" folder too. I found only one way to do that. I must drop old repository and create a new in "Dev" folder. But the version history of original repository is so important for me. There has any solution to import original history to new repository? or Mercurial has another support to change the root folder of repository?
Thanks.
You can
use the convert extension to create a new repo with the aligned files (see the --filemap option)
create a Source folder in your repo and move all files within there
The first one provides a cleaner history, while the second one does not invalidate existing clones.

Using Mercurial (hg), how to push just one file or one directory out?

Using Mercurial, we can commit one file by using
hg commit file.rb
or 1 folder
hg commit foldername
But how can we push just 1 file or 1 folder out?
The whole project can be pushed using
hg push ssh://peter#192.168.1.102//project/code/preliminary
but there seems to be no way to push out just 1 file or 1 folder?
I tried the following and they don't work:
hg push ssh://peter#192.168.1.102//project/code/preliminary app/views/index.html.erb
or
hg push ssh://peter#192.168.1.102//project/code/preliminary/app/views/index.html.erb
That's not really possible to do with Mercurial. The whole point of Mercurial (and Subversion and git and pretty much every version-control system since CVS) is that you deal with changesets; each commit is a set of changes to one or more files. push and pull only know about commits, not about each part of every commit.

tortoisehg and subrepos

I can't get Tortoisehg (1.0) to work with subrepos
I have a directory structure like this:
root
.hg
.hgsub
.hgsubstate
Customer1
Project1
.hg
foo.txt
Project2
.hg
Customer2
Project3
.hg
the .hgsub file under root looks like
Customer1\Project1=Customer1\Project1
Customer1\Project2=Customer1\Project2
Customer2\Project3=Customer2\Project3
If modify the file Customer1\Project1\foo.txt and commit from the root it works
>hg ci -m "command line commit"
committing subrepository customer1\project1
in Tortoisehg customer1\project1 is displayed with status S (subrepo)
but when commiting I get a message
abort: customer1/project1: no match under directory!
Is this scenario not supported or am I doing something wrong?
The doc says:
"TortoiseHg 1.0 introduced rudimentary support for subrepositories, and only in the commit / status tool. When Mercurial considers a subrepo as dirty, it will appear in the commit tool as a special entry in the file list with a status of S. If a subrepo is included in the file list of a commit, the subrepo is committed along with the other changes, updating the .hgsubstate file in the main repository root."
I had pretty much the same problem and started trying a whole bunch of variations and I finally got it working for me by using a forward-slash (/) on both sides of the equals sign and not a back-slash (\) anywhere.
So try...
Customer1/Project1=Customer1/Project1
Customer1/Project2=Customer1/Project2
Customer2/Project3=Customer2/Project3
Also, when it was not working, my .hgsubstate file only had a bunch of zeros in it. When it started working, it had a genuine GUID in it.
I was able to get past this problem by committing using the command line for the main repo.
hg commit -m 'Updated subrepo'
I had the same problem:
In one of my repositories committing of one of my changed subrepo modules failed with message
"abort: mysubrepo: no match under directory!"
The reason:
TortoiseHG fails to commit to the subrepository because it handles folder names case-sensitive!
Example:
Your original repository:
C:\Shared\MySubRepo
Cloning this as a subrepo into another repository by command line
hg clone C:\shared\mysubrepo <--- Note the lower cases!
will create a subrepo folder mysubrepo inside your parent repository.
Adding it to the .hgsub file as usual (I always use the platform independent '/' instead of '\', so I don't think that's the reason for the error).
Trying to commit with --subrepos TortoiseHG will end up with the "no match under directory!" error. However, commiting by command line works.
After renaming the subrepo folder mysubrepo to MySubRepo (as the original folder with upper cases) TortoiseHg could commit successfully!
Maybe you have to edit the folder name also in the hgrc file, but I'm not sure if this is really neccessary, because I renamed it in the file before figuring out, that there are canse-sensitive differences in the folder name iteself. Also removing the repository from TortoiseHg Workbench's repository registry and readding it may be needed (and/or restart of the Workbench as well).
I think your problem is with specifying "Customer1\Project1" as a sub repository because Customer1 should be a nested repository as well.
Customer1 and Customer2 should both have '.hgsub' files describing the subrepos inside them (Project1/2)
Remake your Customer1 repository elsewhere and clone Project1 and Project2 into it. Add Project1 and Project2 entries to the '.hgsub' file within Customer1.
Then do the same for a Customer2 repository.
Remember that nested repositories can themselves be nested so create a 'root' repository and then clone Customer1 and Customer2 into it remembering to add entries to the .hgsub file.
Commit 'root' and you should be fine.
The key is to push changes from all instances of a subrepos to its clone master so that other clones that include that subrepos are able to pull that revision if needed.
I have all master repos in the same parent folder on my machine so it makes putting relative paths inside '.hgsub' files such as '../Project1' or '../Customer1' a simple way to push changes to my local clones from our central server.
As far as using TortoiseHG, you will be fine with v1.0 as it will create and manage the '.hgsubstate' file in a nested repository as long as you have already created the '.hgsub' file!
Adding my 2 cents.
I was receiving this error abort: customer1/project1: no match under directory on Windows in the following scenario:
repo was in a folder named MyFolder (note the upper case)
repo had a subrepo
some files (only some!) in the parent repo were commited using myfolder/filename.ext (note the lowercase)
Everything works fine, commandline commits work fine, but Tortoise complains.
Rename the files (find the lowercase ones using hg status --all and you're fine)