I am familiar with TFS and Vault, but having just started using Mercurial I seem to be getting into a bit of a mess.
Heres what I (think) I've done:
-Created a central repository on bitbucket.org
-On my desktop PC, cloned repository from bitbucket, added files, commit them, push them to bitbucket
-On my laptop, cloned repository from bitbucket, pulled files, added more files, commit them, push them to bitbucket
I've continued to add, edit etc on the different computers.
Now I've noticed that some files from each computer are not in the bitbucket repository, and therefore only in the local repository. No amount of pulling and pushing seems to get it into the bitbucket repository.
What is the most likely thing I've done wrong?
Is there a way to 'force' by changes up to the bitbucket repository?
Did they get into your local repository? I suspect not, i.e. they were new files that were not added to the commit. Use hg add to add them to the changeset before committing or whatever the equivalent is for whatever mercurial interface you're using.
Edit:
Here's the help from Mercurial:
C:\Users\Bert>hg add --help
hg add [OPTION]... [FILE]...
add the specified files on the next commit
Schedule files to be version controlled and added to the repository.
The files will be added to the repository at the next commit. To undo an
add before that, see "hg forget".
If no names are given, add all files to the repository.
...
See Mercurial: The Definitive Guide (a.k.a. the hg "red book") for more info:
http://hgbook.red-bean.com/read/mercurial-in-daily-use.html
Telling Mercurial which files to track
Mercurial does not work with files in your repository unless you tell it to manage them. The hg status command will tell you which files Mercurial doesn't know about; it uses a “?” to display such files.
To tell Mercurial to track a file, use the hg add command. Once you have added a file, the entry in the output of hg status for that file changes from “?” to “A”.
$ hg init add-example
$ cd add-example
$ echo a > myfile.txt
$ hg status
? myfile.txt
$ hg add myfile.txt
$ hg status
A myfile.txt
$ hg commit -m 'Added one file'
$ hg status
use "hg -v help add" to show global options
Related
I initially committed my project to a hg repo with the following structure:
myapp/
fizz/
buzz.txt
foobar.cfg
whistlefeather/
vroom-vroom-party-starter.xml
I did so using the following commands:
hg add
hg commit -m "Initial commit."
hg push
I then changed my directory structure locally to look like this:
myapp/
buzz/
fizz.txt
config.foobar
whistlefeather/
vroom-vroom-party-starter.xml
I then ran the same following commands:
hg add
hg commit -m "Changing some things."
hg push
When I go to the remote repo, I see it has the following structure (?!?):
myapp/
fizz/
buzz.txt
buzz/
fizz.txt
foobar.cfg
config.foobar
whistlefeather/
vroom-vroom-party-starter.xml
What commands can I run to push/purge the old directories/files from the remote repo (and so that it reflect the directory struture on my local machine)?
The hg add command you issued prior to your second commit did not actually remove files from under version control, but only added new ones. Now your repository is actually a melange of old and new files.
To add new files and remove missing ones, use hg addremove command or hg commit -A
It's actually simple to remember:
hg add adds files to the repo
hg remove removes files
hg move moves or renames files
hg addremove looks at current working dir and adds and removes files from the repo such that only the files still being present will continue to be tracked.
Each of these operation can be done in any sequence. And only a commit will actually create a changeset
I have a repository which will be cloned.
I go to directory of the repository and type the following command to get the branches.
hg branches
As the reuslt I get the
blank 0:4d82003d3fc7
And also I get the size of the repository using
du -sh ./
It prints
312M ./
This repository containes the following.
ls -a
. .. dummy .hg .hglf
Now when I clone it using this command
hg clone /path/libname -r blank
I get the new repository, the size of which is only 52 kbts and it containes
. .. dummy .hg .hglf
I also clone it without -r blank option
hg clone /path/libname
And get the same result. I suppose if repository have 312M size, the cloned repository also should have a comparable size. Where is a problem ?
The original repository has a '.hglf' file. This indicates that (most likely) it uses 'largefiles'. Largefiles are stored on the server, and are only downloaded for a specific revision if you update to that revision. There are a few possibilities:
You are not on a revision that uses largefiles. Update to one that does and you'll see a larger size.
You don't have the 'largefiles extension' enabled. Enable it and try to clone again, you should see a difference. To enable largefiles, add to your .hgrc:
[extensions]
largefiles =
Starting with Mercurial 3.4 (not yet released as of this writing), the largefiles extension will be enabled automatically when cloning a repository with largefiles.
I have come across a problem that I "think" can only be resolved using patches.
I cloned a project from our main repository, made quite a few changes (updates, deletion of files & directory and additions) to it. These changes are not even committed. The problem is, project from the main repository has been deleted/removed and recreated as a new project (name is same, all the directory structures everything is same as before). I cloned that project again from the main repository and would like to transfer all my uncommitted changes to it.
I am still exploring the hg patch to resolve that. It would be helpful if someone could confirm that creating and adding a patch IS the right approach to this, any resources explaining the process would be of great help.
You're correct — a patch is what you need to transfer the information from one repository to another (unrelated) repository. This will work since the files are the same, as you note.
So, to transfer your uncommitted changes from your old clone, you do
$ hg diff -g > uncommited.patch
$ cd ../new
$ hg import --no-commit ../old/uncomitted.patch
That will restore the information saved in the patch. This includes information about files that are added or renamed in the old clone.
The following steps can be performed with a standard Mercurial install:
Commit the changes in your local repository. Note the revision number.
Use "hg export -r REV >patch.diff" to create a patch.
Clone the new repository.
Use "hg import patch.diff" to apply the patch to the new repository.
Example
C:\>hg init example
C:\>cd example
C:\example>echo >file1
C:\example>hg ci -Am file1
adding file1
C:\example>hg clone . ..\example2
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
C:\example>rd /s/q .hg
C:\example>hg init
C:\example>hg ci -Am same-but-different
adding file1
At this point example and example2 have identical contents, but the repositories are unrelated to each other due to deleting and reinitializing the .hg folder.
Now make some changes and commit them in one of the repositories, then export them as a patch:
C:\example>echo >>file1
C:\example>echo >file2
C:\example>hg ci -Am changes
adding file2
C:\example>hg export -r 1 >patch.diff
Below shows that the other repository can't pull the changes, because of the reinitialization. It can, however, apply the patch successfully:
C:\example>cd ..\example2
C:\example2>hg pull
pulling from c:\example
searching for changes
abort: repository is unrelated
C:\example2>hg import ..\example\patch.diff
applying ..\example\patch.diff
I would first make copies of everything so you have a way of backtracking.
Then, in the working copy with the changes, I would first delete the .hg directory, then copy in the .hg directory from the new repo. This basically transfers all of the changed files into the new repo without the need to delete any files and directories.
You will still need to tell the repo about whether to remove any files marked as missing. You will also have to handle renames manually. If this is a small number of operations, it's easier than trying to use the patch method.
Once this is done, commit your changes and push, if necessary.
seems like what you want is patch queues. In that you have uncommitted changes, and you want to pull from the new repo before committing them....
$ hg qinit -c # initialize mq for your repo containing the uncommitted changes
$ hg qnew name_of_patch # create patch that contains your uncommitted changes
$ hg qpop # resets your working dir back to the parent changeset
no worries though, your changes are safe and sound in .hg/patches/name_of_patch to see for yourself.....
$ cat .hg/patches/name_of_patch
now pull in the new repo
$ hg pull -u http://location.of.new/repo # pull in changes from new repo update working dir
$ hg qpush # apply your uncommitted changes to new repo
If you are lucky you will have no merge conflicts and you can go ahead and commit the patch by....
$ hg qfinish -a # change all applied patches to changeset
And then if you want....
$ hg push http://location.of.new/repo
If the repos are unrelated, just init a patch repo on your new repo. and manually copy the patch in and add it to .hg/patches/series file.
assuming patch was created. clone new repo
$ hg clone http://location.of.new/repo ./new_repo
init patch repo
$ cd ./new_repo && hg qinit -c
copy patch
$ cp ../old_repo/.hg/patches/name_of_patch .hg/patches/
edit series file using an editor of some sort
$ your_favorite_editor .hg/patches/series
name_of_patch # <---put this in the series file
apply your patch to new repo
$ hg qpush
if no merge conflicts and you are convinced it works
$ hg qfinish -a
If the layout is the same, you can just copy all the files over (excluding .hg) and then use hg addrem.
Try to look into the MQ plugin, it does exactly this if I recall. I've never had a use for that though, so I can't say.
If the old repository was simply moved/cloned to a new URL then you could simply change the remote repository you talk to the new one.
If, however, it was recreated from the ground up (even with the same structure) then I don't believe Mercurial has any built-in functionality to help you here. Mercurial patches reference specific changesets which won't exist in your new repository.
You could use a merge tool to perform the diff and bring across any changes you made.
Edited To answer the question in the comment:
When you clone the repository you are taking a complete snapshot of the entire change history - along with the associated change-set IDs, etc.
Mercurial tracks changes by change-sets to the repository, rather than at the file level like Subversion.
If you clone, then you can easily push/merge into another repository that was also cloned from the same source.
If you recreated the repository then the change IDs won't match, and can't be merged in Hg.
The only option in this scenario would be to use a Merge tool which will let you see mismatches in files/folder structure.
Also: Worth pointing out http://hginit.com/ because it explains (indirectly) some of this.
I am looking for best practices to do the following:
When I need to implement a feature or fix a bug, I am creating new Mercurial repository from the main one (a trunk).
Then, within some days, or weeks, I am implementing the task in newly created repository, making commits and periodically merging with trunk. After the code in new repository will pass all code reviews, I should provide a repository with all changes collapsed into single revision.
My common way to do this (rdiff extension should be enabled):
hg clone ~/repos/trunk ~/repos/new-collapsed
cd ~/repos/new-collapsed
hg diff ~/repos/new > new.diff
patch -p1 < new.diff
hg commit
This works almost well except when there are binary files present in the changes from ~/repos/new. Another way could be:
hg clone ~/repos/trunk ~/repos/new-collapsed
cd ~/repos/new-collapsed
hg pull ~/repos/new
hg update
hg rollback
then resolve possible conflicts and manually commit the changes
Both ways look for me somewhat ugly and non-native, so I am looking how this operation could be simplified. I've played with rebase extension, but seems its hg rebase --collapse command does not work with workflow described above.
Any ideas are welcome.
Sounds like a good case for mercurial queues.
I do something similar with the histedit extension.
My workflow is something like:
clone a central repo
commit incremental changes to local repo
clone my local repo to make collapsed repo
hg histedit and select/discard/fold the revisions as needed
hg push the collapsed repo to central repo
pull central repo to local or refresh local from scratch
I ensure that my local repo never gets pushed to the central repo by adding an invalid default-push path to the .hg/hgrc file in the local repo root directory.
Solved: Just add
[diff]
git = True
to your hgrc file, and then use my first solution with rdiff extension, replacing patch with hg import:
hg clone ~/repos/trunk ~/repos/new-collapsed
cd ~/repos/new-collapsed
hg diff ~/repos/new > new.diff
hg import new.diff
hg commit
I have two computer : the desktop in my company and the portable computer in my home.
Now I want to use the hg to synchronize the project between them using a "USB removable disk".
So I wonder how to implement it?
THe pro in my desktop is : D:\work\mypro.
I use the following command to init it:
hg init
Then I connect to the USB disk whose volume label is "H",and get a clone using:
cd H:
hg init
hg clone D:\work\mypro mypro-usb
ANd in my portable computer I use:
cd D:
hg clone H:\mypro-usb mypro-home
However I do not know how to do if I modify some files(remove or add and modify) in the mypro-home,how to make the mypro-usb changed synchronizely,also I want the mypro in my desktop synchronizely.
How to do it?
---------------The following is added after I get an answer from richj----------------
to richj:
Thanks for your reply.
The following is my practice: Pro-Com is the project(initialized as a repository) in my desktop, Pro-USB is the repository in my USB, the Pro-Home is the repository in my home computer.
When I make some change in the Pro-Com, I use the following command:
hg add
hg push Pro-USB
Then I change the directory to Pro-USB,using:
hg update
hg push Pro-Home
In my home computer I run:
hg update
(make some edition)
hg commit
hg push Pro-USB
Then the repository in the USB is the same as that of my home computer,I can push it to my desktop.
In my opinion,operation between repository can be done just by "hg push" and "hg pull",the other commands like "hg update" "hg import" just work between a working-copy and its repository.
Is my understanding right?
To push changes from your working repositories back to your USB drive:
hg push
To get the latest changes from your USB drive:
hg pull
hg update
These two commands can be combined together like this:
hg pull -u
If you want to see which change sets are available to be pushed or pulled use:
hg outgoing
hg incoming
respectively. Any changes that you make to your local file system must be committed to the repository using:
hg commit
before they can be pushed or pulled.