I have a Mercurial main-repository with one sub-repository, like this:
Main
.hg
.hgsub
.hgsubstate
<some_regular_files_and_subdirs>
Sub
.hg
<some_regular_files_and_subdirs>
And I wish to tag Sub, only, while keeping Main/.hgsubstate up-to-date (i.e. point to the changeset of Sub resulting from the tagging process).
I don't want to tag the main-repository.
Is that possible without tagging from within Sub and do some magic to get Main/.hgsubstate up to date?
When updating a subrepo, you always need to perform a commit on the main repo to begin using that subrepo revision. Therefore, you can't exactly do what you want from the subrepo itself, you will have to enter the main repo and execute a single command there.
from the command line:
(navigate to subrepo directory)
> hg tag <tagName>
(navigate to main repo directory)
> hg commit -m "updating to subrepo tag <tagName>"
After you have created the subrepo tag and updated the subrepo to that tag, performing a commit from the top level (ie: Main) should update .hgsubstate and does not require you to tag the Main repo. In fact, changing the revision of any subrepo should trigger a change in the .hgsubstate file, which can be committed in the main repo without a tag.
Something like below?
hg -R Sub tag tagname
hg -R Sub commit -m "Comitting tag"
Related
There is a commit in my hg repository with hash 123abc. This is the last commit I made in the repo. When I run hg diff --from 123abc, I see no output. When I run hg log --graph, I see an # next to 123abc.
In Git this commit would be called "HEAD". I'm not sure what it's called in Mercurial. It is not the "tip", because I pulled other changes after the last time I committed (and hg log -r tip shows commit 456def).
What is this commit/head called?
Mercurial calls this the "parent" or the "parent revision of the working directory", and you can see it by running hg parent, hg id, or hg summary.
You can refer to it as . with the hg log command:
hg log -r . # show the commit message for the parent
If 123abc has no children, then it is a "head".
A head is a changeset with no child changesets. The tip is the most
recently changed head. Other heads are recent pulls into a repository
that have not yet been merged.
(https://www.mercurial-scm.org/wiki/Head)
Regardless whether the current working directory derives from a head or a non-head, I would refer to the commit that precedes it as the "working directory parent" changeset or commit. (That may just be the term my team uses - not sure it is "official".)
The parent may be visible in a GUI tool (like Tortoise) or you can get it using hg parent.
Based on the statements about 456def I'm a little confused whether it has no children, or not? (Maybe update the question to clarify / add more detail)
So I have a main Mercurial repo composed of 3 sub-repos.
Usually the right way to commit/push that I understood is the following:
hg commit -Sm 'Fixed a bug' # This commit was done from the main repo
hg push
I did a mistake and commit/push from one of the sub-repos:
hg commit -m 'Fixed a bug' # This commit was done from a sub-repo
hg push
Now, the other coder that will pull/update the main repo won't see my changes in the sub-repo.
What is the right Mercurial way of fixing that?
Manually modifying the .hgsubstate file in the main repo and commit/pushing it?
If so, I understand that the first part of the ID is the tip of the last sub-repo changeset but what about the rest of the ID? How is it generated?
OR
Waiting to the next commit/push so the .hgsubstate file is fixed with the latest changeset?
OR
Committing and pushing a dummy changeset?
OR
Something else...
I do not know if I understood your problem correctly but to me it seems like the correct way would be to step into the subrepo do a pull and update, then step out to the main repo and do commit/push.
See https://www.mercurial-scm.org/wiki/Subrepository#Synchronizing_in_subrepositories
I have got a question regarding suprepositories. Our project is set up like this:
+ projectA
+ some files
+ dependencyA
+ some files
dependencyA is a subrepository. It was created this way:
cd projectA
mkdir dependencyA
cd dependencyA
hg init
hg pull ssh://hg#somerandomiphere/dependencyA
cd ..
echo dependencyA = ssh://hg#somerandomiphere/dependencyA > .hgsub
hg add
hg commit
hg push
If I make changes to the suprepository, then commit and push them from main project. Both of them will be pushed to the server since its recursive. Now my colleague wants to pull changes from the server. But since nothing was changed in the main project, it wont work. But if I change something in the main project and push it to server. Upon hg pull he will get the newest changeset and if he does hg update then, it will update the subrepository as well. This is expected behaviour.
Now my question would be, if there is a way to pull changes, but only for subrepository without making a new clone of it or what would be the best way to do it.
Subrepository in Mercurial wiki, p. 2.5 "Pull"
The 'pull' command is by default not recursive. This is because
Mercurial won't know which subrepos are required until an update to a
specific changeset is requested. The update will pull the requested
subrepositories and changesets on demand. To get pull and update in
one step, use 'pull --update'.
Note that this matches exactly how 'pull' works without
subrepositories, considering that subrepositories lives in the working
directory:
'hg pull' gives you the upstream changesets but doesn't affect your working directory.
'hg update' updates the contents of your working directory (both in the top repo and in all subrepos)
It might be a good idea to always pull with --update if you have any
subrepositories. That will generally ensure that updates not will miss
any changesets and that update thus not will cause any pulls. If the
pull with update fails due to crossing branches then 'hg update' must
be used to get all the subrepository updates.
What was suggested above works like I thought it would. The real problem was my way of creating a subrepository.
Instead of:
cd projectA
mkdir
dependencyA
cd dependencyA
hg init
hg pull ssh://hg#somerandomiphere/dependencyA
It should have been a simple:
hg clone ssh://hg#somerandomiphere/dependencyA dependencyA
As we know .hgsusbtate will lock the subrepo on specific revision after commit. This is what happened, but (!) doing hg pull in subrepository ended with an error
paths cannot contain dot file components
So this means my subrepo was locked on the revision it was updated after commit and it could not pull changes from its repository due to the error shown above. Why this happened is explained pretty well in this accepted answer.
Solution:
cloning is the way to go
We're using a local central repository where everyone pushes to and pulls from. Until recently this repository only contained the .hg folder. Then someone went ahead and committed directly in the central repository creating an "island" changeset with no parent (parent = -1) nor child. The correct way would have been to add it in a local repository and push the changes.
Is there any way to get the working copy of the central repository to get back to the state where it only contain .hg and not be associated with a specific changeset?
The command:
hg update null
Updates a repository's working directory to the point before the first commit, so there are no files in the working directory and hg parents shows -1.
You'll still need to remove the commit if you don't want it, but that's a separate question/issue.
Since this is your local central repository and these are commands that edit history, please take every precaution, like trying things out on a copy of the repository first.
hg rollback (to remove the last repository change)
https://www.mercurial-scm.org/wiki/Rollback
Roll back the last transaction in a repository.
hg strip (to remove specific revisions)
https://www.mercurial-scm.org/wiki/Strip
hg strip rev removes the rev revision and all its descendants from a repository.
Also see:
https://www.mercurial-scm.org/wiki/EditingHistory
If you catch your mistake immediately (or reasonably soon), you can just use hg strip REV to roll back the latest (one or more) changes. ...
Edit: This answers the question in its original form. The OP has since edited the question.
Just delete everything except the .hg folder.
If I understand correctly what happened, someone changed into the repository directory and committed a single file as an 'added file' without first checking out any changeset from the active directory.
What you ended up with is something like the following history graph:
0:a43f 1:2843 2:bc81 3:2947
o ------ o ------ o ------ o
4:228f
o
where changeset 4:228f has the "null id" as its parent changeset.
Depending on whether you want to keep changeset 4:228f or not, you can follow one of the following strategies:
Option 1: Clone the repository without the offending change
You can create a new clone of the repository, specifying revision 3:2947 as the target revision. This will pull change 3:2947 and all its ancestor changesets into the new repository. Since the offending changeset is not linked into the ancestry of changeset 3:2947, it will not be part of the new clone.
I recommend saving the old repository first, and then moving everything over to a new clone, e.g. any repository-specific setup files you keep in its .hg/ directory.
If your current repository lives in /work/repo/foo, one way to do this would be:
$ cd /work/repo
$ mv foo foo.bak
$ hg clone -r 2947 foo.bak newfoo
Now copy over any .hg/ setup files, e.g. your original .hg/hgrc file:
$ cp foo.bak/.hg/hgrc newfoo/.hg/hgrc
Finally move the new foo repository in place:
$ mv newfoo foo
Option 2: Clone the repository and keep but rebase the change
Do the same as before, but before you move the newfoo repository in place, use the "hg export" command to extract a copy of the offending change from the old repository. Then check out a working copy of the tip-most changeset in the newfoo tree and import the file changes of the offending change as a normal changeset of your current history graph.
So, right before mv newfoo foo, save the patch of the offending change by typing:
$ cd /work/repo/foo.bak
$ hg export -r 228f --git > /tmp/patchfile.diff
then you can check-out the latest revision of the new repository, and re-import the patch on top of your current history:
$ cd /work/repo/newfoo
$ hg update --clean tip
$ hg import /tmp/patchfile.diff
If the offending changeset merely adds a new file, this should work fine and you are ready to move the new repository in place!
Before doing the final rename though, it may be a good idea to remove the working-copy files of the new repository:
$ cd /work/repo/newfoo
$ hg update --clean null
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)