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 =
Related
I have noticed by mercurial repository expanding in size when ever I use repo B to pull changes from repo A.
It seems that TortoiseHG creates files like hg-bundle-r3e6uf.hg10un under .hg directory. These files are usually 1-2MB in size each, so nothing too big, but together they create a lot, and can be an annoyance when doing backups.
This does not seem to happen if I pull changes instantly without reviewing them, or if I use repo A to push changes to B.
These bundle files seem useless as they are not copied when cloning the repository B.
Also the cloned repo is almost half smaller without them, so it is like data in these files wasn't moved to other files either.
Is it possible to:
A) Avoid creating these bundles on pull. (Pushing is option only when I have access to both repos)
B) Use some command to cleanup .hg directory. (Cloning is not very elegant)
EDIT:
When I select 'Incoming' first bundle is created:
% hg --repository C:\temp\hg\testB incoming --quiet --bundle c:\docume~1\username\locals~1\temp\thg.hlngus\CtemphgtestA_iavzew.hg C:\temp\hg\testA
1:d806c8cb0355
2:e0e3b20d5cb2
3:4e803a7ecefc
[command completed successfully Fri Aug 02 09:59:12 2013]
and then 'Accept', the second bundle is created:
% hg --repository C:\temp\hg\testB pull --verbose c:\docume~1\username\locals~1\temp\thg.hlngus\CtemphgtestA_iavzew.hg
pulling from c:\docume~1\username\locals~1\temp\thg.hlngus\CtemphgtestA_iavzew.hg
searching for changes
all local heads known remotely
3 changesets found
adding changesets
adding manifests
adding file changes
added 3 changesets with 3 changes to 1 files
(run 'hg update' to get a working copy)
[command completed successfully Fri Aug 02 10:00:10 2013]
Where as using 'Pull' directly, no extra bundles are created:
% hg --repository C:\temp\hg\testB pull --verbose C:\temp\hg\testA
pulling from C:\temp\hg\testA
searching for changes
all local heads known remotely
3 changesets found
adding changesets
adding manifests
adding file changes
added 3 changesets with 3 changes to 1 files
(run 'hg update' to get a working copy)
[command completed successfully Fri Aug 02 10:01:52 2013]
It seems this is TortoiseHg specific issue. Solution is either use push or use pull directly from command line to avoid extra bundles. Only (safe) way to cleanup seems to be the repository cloning.
I've got a project running under Mercurial and am finding a lot of situations where a file needs manually merging, when I believe it should be able to merge automatically. I am wondering whether there are any options that can be given to Mercurial to help it out in these areas.
The project has an underlying platform with a couple of hundred files that can't be edited on the project. When the platform is updated, the project gets updated versions of these core files outside of Mercurial. The sequence I'm seeing repeatedly is:
On central dev system (linked to the core platform update mechanism):
Get a new version of core platform.
Commit these changes e.g. hg commit -m "New platform release"
Push to central mercurial server
On my Linux box:
Commit local changes
Pull from central mercurial server, and try to merge
Find merge conflicts on core files
The last two core files I've had to merge have no changes between the base and local versions (the access time is updated during a build, but the content is the same). The only changes are on the remote revision I'm merging with.
The only non-standard configuration I'm aware of is that the central mercurial instance is running under Rhodecode, with a commit hook setup to update a Redmine repository.
Is there anything else that can be configured in mercurial to help it figure out merges?
You can redo a merge with --debug to get more information about a merge. That is, take your repository and do
$ cd ..
$ hg clone my-project -r 123 -r 456 merge-test
where 123 and 456 is the two parents of the merge you want to examine closer. Then run
$ hg merge --debug
to see what Mercurial says. It should look like this if the file foo has only been changed in the branch you're merging in:
$ hg merge --debug
searching for copies back to rev 2
resolving manifests
overwrite: False, partial: False
ancestor: 932f5550d0ce, local: b0c286a4a76d+, remote: c491d1593652
foo: remote is newer -> g
updating: foo 1/1 files (100.00%)
getting foo
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
Here I was on revision b0c286a4a76d and merged with c491d1593652.
You can also use
$ hg status --rev "ancestor(b0c286a4a76d, c491d1593652)" --rev "c491d1593652"
M foo
$ hg status --rev "ancestor(b0c286a4a76d, c491d1593652)" --rev "b0c286a4a76d"
M bar
to double-check which files have been changed between the ancestor revision and the two changesets you're merging. Above you see that I changed foo on one branch and bar on the other.
If you see a platform file appear in both status lists, well then something went wrong in your procedures and this can explain the merge conflicts.
If this isn't enough to figure out what went wrong, then I suggest asking this question on the Mercurial mailinglist. That's a great place for discussion and bug-hunting — much better than Stack Overflow.
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.
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.
So I keep making a silly mistake in Mercurial. Often times, I'll start work without doing an "hg pull" and an "hg update." When I try to push my changes, I get an error.
Is there any way to delete my local commits so I can avoid creating multiple heads, branches, etc? I just want to delete my local commits, merge my changes with the tip, and then re-commit. Sounds simple, right? I can't seem to find any way to easily delete local commits so I can cleanly merge with the tip.
Again, I'm only trying to delete local commits made with "hg ci". I don't want to modify files, revert, etc.
Enable the "strip" extension and type the following:
hg strip #changeset# --keep
Where #changeset# is the hash for the changeset you want to remove. This will remove the said changeset including changesets that descend from it and will leave your working directory untouched. If you wish to also revert your committed code changes remove the --keep option.
For more information, check the Strip Extension.
If you get "unkown command 'strip'" you may need to enable it. To do so find the .hgrc or Mercurial.ini file and add the following to it:
[extensions]
strip =
Note that (as Juozas mentioned in his comment) having multiple heads is normal workflow in Mercurial. You should not use the strip command to battle that. Instead, you should merge your head with the incoming head, resolve any conflicts, test, and then push.
The strip command is useful when you really want to get rid of changesets that pollute the branch. In fact, if you're in this question's situation and you want to completely remove all "draft" change sets permanently, check out the top answer, which basically suggests doing:
hg strip 'roots(outgoing())'
If you are using Hg Tortoise just activate the extension "strip" in:
File/Settings/Extensions/
Select strip
Then select the bottom revision from where you want to start striping, by doing right click on it, and selecting:
Modify history
Strip
Just like this:
In this example it will erase from the 19th revision to the last one commited(22).
Modern answer (only relevant after Mercurial 2.1):
Use Phases and mark the revision(s) that you don't want to share as secret (private). That way when you push they won't get sent.
In TortoiseHG you can right click on a commit to change its phase.
Also: You can also use the extension "rebase" to move your local commits to the head of the shared repository after you pull.
As everyone else is pointing out you should probably just pull and then merge the heads, but if you really want to get rid of your commits without any of the EditingHistory tools then you can just hg clone -r your repo to get all but those changes.
This doesn't delete them from the original repository, but it creates a new clone that doesn't have them. Then you can delete the repo you modified (if you'd like).
I came across this problem too. I made 2 commit and wanted to rollback and delete both commits.
$ hg rollback
But hg rollback just rolls back to the last commit, not the 2 commits. At that time I did not realize this and I changed the code.
When I found hg rollback had just rolled back one commit, I found I could use hg strip #changeset#. So, I used hg log -l 10 to find the latest 10 commits and get the right changeset I wanted to strip.
$ hg log -l 10
changeset: 2499:81a7a8f7a5cd
branch: component_engine
tag: tip
user: myname<myname#email.com>
date: Fri Aug 14 12:22:02 2015 +0800
summary: get runs from sandbox
changeset: 2498:9e3e1de76127
branch: component_engine
user: other_user_name<name#email.com>
date: Mon Aug 03 09:50:18 2015 +0800
summary: Set current destination to a copy incoming exchange
......
$ hg strip 2499
abort: local changes found
What does abort: local changes found mean? It means that hg found changes to the code that haven't been committed yet. So, to solve this, you should hg diff to save the code you have changed and hg revert and hg strip #changeset#. Just like this:
$ hg diff > /PATH/TO/SAVE/YOUR/DIFF/FILE/my.diff
$ hg revert file_you_have_changed
$ hg strip #changeset#
After you have done the above, you can patch the diff file and your code can be added back to your project.
$ patch -p1 < /PATH/TO/SAVE/YOUR/DIFF/FILE/my.diff
You can get around this even more easily with the Rebase extension, just use hg pull --rebase and your commits are automatically re-comitted to the pulled revision, avoiding the branching issue.
hg strip is what you are looking for. It's analogous of git reset if you familiar with git.
Use console:
You need to know the revision number. hg log -l 10. This command shows the last 10 commits. Find commit you are looking for. You need 4 digit number from changeset line changeset: 5888:ba6205914681
Then hg strip -r 5888 --keep. This removes the record of the commit but keeps all files modified and then you could recommit them.
(if you want to delete files to just remove --keep hg strip -r 5888
If you are familiar with git you'll be happy to use histedit that works like git rebase -i.
[Hg Tortoise 4.6.1]
If it's recent action, you can use "Rollback/Undo" action (Ctrl+U).
In addition to Samaursa's excelent answer, you can use the evolve extension's prune as a safe and recoverable version of strip that will allow you to go back in case you do anything wrong.
I have these alias on my .hgrc:
# Prunes all draft changesets on the current repository
reset-tree = prune -r "outgoing() and not obsolete()"
# *STRIPS* all draft changesets on current repository. This deletes history.
force-reset-tree = strip 'roots(outgoing())'
Note that prune also has --keep, just like strip, to keep the working directory intact allowing you to recommit the files.