I have a repository named repo1, and it's my base.
I clone it into repo2.
I have another repository containing some unrelated files and history, named other_repo.
Thanks to hg convert, I can import a subset of other_repo into repo2, while keeping the history of the files:
hg convert --filemap my_file other_repo temp_repo
cd repo2
hg pull -f temp_repo
This is working flawlessly.
However, now, if I bundle the changes in repo2, and try to unbundle them in repo1, I get the following error:
adding changesets
transaction abort!
rollback completed
abort: 00changelog.i#82dc9cd3be46: unknown parent!
Well, that's normal. The new parent comes from the other_repo, and it is needed now.
Note that hg pull in repo1 from repo2 is working fine.
In such a case (when the repository's history is fine, hg verify doesn't complain, I didn't strip anything), is there a way to force the unbundle action?
No, there isn't.
The bundle is a diff between the parent and the child, you only got the changes, and without the parent, you can't reconstruct the child changeset.
So get the parent into the repository before you try to unbundle.
Or create a new bundle, without that changeset.
Or, do some history rewriting in the source repository first, so that you don't need the parent.
Regardless, you can't force this to complete without rethinking your approach.
Related
We have a master repository located on a separate server. I originally cloned the default branch and made my changes locally. I have locally commited those changes. However, there has been a branch created on the master repository that I would like to push my changes to. Below is the description of my attempt at getting this accomplished.
I have cloned the branch. I am trying to export my changes from local default like so:
C:\hg\default>hg export -g -o mypatch -r tip
and when trying to import them into the clone of the new branch, I get the following:
C:\hg\newBranch>hg import C:\hg\default\mypatch
applying C:\hg\Fill1\mypatch
patching file .hgignore
Hunk #1 FAILED at 11
1 out of 1 hunks FAILED -- saving rejects to file .hgignore.rej
abort: patch failed to apply
I can manually fix the .hgingore.rej file just fine. The problem is that the patch also contains files that were moved. Instead of the files showing as moved, I get the following when running hg status:
C:\hg\newBranch>hg status -C
M someOtherFilesThatLookAsExpected.txt
! originalLocaion\fileA.txt
? newLocation\fileA.txt
This missing and new status is for all files that were moved in the commit contained the applied patch. Am I doing something wrong? Do I always have to manually move files when applying a patch? Is there an easier way to accomplish this branch transfer?
That's a bit difficult to answer without knowing more about your repository structure, but here's how I'd go about it without knowing more. I'm assuming that the reason for the conflict is that there are conflicting changes in the same branch of the repository.
First, get the contents of the newBranch repository:
cd c:\hg\default
hg pull c:\hg\newBranch
Then, either merge or rebase your changes on top. If you are working on the same branch, then just using
hg pull --rebase c:\hg\newBranch
in lieu of the regular pull should do (assuming you have rebasing enabled). Otherwise, do an explicit merge or rebase of the two heads that you need to reconcile. Finally, do:
hg push -r tip c:\hg\newBranch
in order to get your (now reconciled) changes back into newBranch.
Unless you have very specific and unusual requirements, push and pull should be your normal way to sync repositories or part of them (note that using -r will only push/pull the respective branch). Export/import are rather low-level mechanisms that may not give you the benefits of the standard machinery that handles renames, three-way merging logic, etc.
I accidentally stripped the wrong changesets; however, I saved backups, but when I try to unbundle them using hg unbundle .hg/strip-backup/faa0a1895b97-backup.hg, I get the following error:
adding changesets
transaction abort!
rollback completed
abort: 00changelog.i#561fe01204b5: unknown parent!
What can I do to correct this?
Here's the entire output from hg verify:
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
If unbundle is telling you that it can't apply the bundle then the parent of that "first" changeset it that bundle, the bundles base, doesn't exist in your repo. Since repos never lose changesets using normal mercurial commands (strip isn't normal) then it seem you used strip or some other history-altering-not-normal-usage command to alter or remove that changeset.
Try going through all the .hg/strip-backup/ files and applying them one by one. Maybe one of them does apply and contains the parent the the strip backup you're trying to apply requires.
Tl;Dr: no normal mercurial command ever deletes anything, and the non-normal ones that do create backups. Unless you deleted the file out of band the data is there somewhere.
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
TLDR: I have an HG bundle with parent X, but revision X does not exist in my repo. However, I am sure that the files of revision Y are identical to revision X. How do I apply the bundle?
Background:
I use hgsubversion to interact with an SVN repo.
There were some changes I did not want to commit. hgsubversion does not support partial pushes.
I used to workaround by manually creating temporary exports/patch files, or manually restoring .orig files (result of hg revert).
In this case I committed the changes I did not want to push, then used hg strip, then pushed, then tried to use hg unbundle .hg/strip-backup/file.
Problem: hgsubversion replaces the original changeset with a new one it imports from SVN after it's committed it. Result: the changeset ID changes. This is a problem because now hg unbundle no longer works, as it relies on the parent changeset being there (but it's been stripped).
Ironically, hgsubversion itself uses strip and thus has a backup file I can use to strip the new rev, add the stripped old revision, then apply the bundle with my revisions, export the patch, strip both, and restore the SVN revision. But this sounds... extremely painful and stupid. Is there nothing better I can do?
(hg transplant doesn't seem to like the bundle without having the parent in the repo, either)
It's effectively impossible to use a bundle without the bundle's precise parent changesets. Bundles consist of compact binary deltas that can only be applied to the precise binary source. There is no 'context' available that would allow Mercurial to guess how to apply them to other revisions the way patch does. In core Mercurial, this is never an issue because changesets are never removed, but extensions like hgsubversion and mq break the rules.
(If you can recover the stripped changesets from a backup bundle in .hg/strip-backup, you can then rebase your changes and strip again.)
Background: After hitting an issue with hgsubversion pushing only 1 revision successfully, I got lazy in my commits (partial commits are possible if you update to the latest revision you want to push), and ended up starting to commit everything. So I killed the push and for the first time it failed to keep my later revisions.
I tried recover, but that was not able to find the parent commit. What worked for me was restoring the ...-backup.hg file (there was a ...-temp.hg file in strip-backup too).
The strange thing (which is why I'm answering this) is that it only gave me a warning about the parent not being there (I have no idea why)...
warning: ignoring unknown working parent d5663567bc4b!
adding changesets
adding manifests
adding file changes
added 21 changesets with 1255 changes to 941 files
(run 'hg update' to get a working copy)
BTW, I'm running Mercurial version 2.0
Is there a way to clone a repo that comes with subrepos, but without having Mercurial pull all the subrepos?
It appears that while hg clone -U can be used to obtain an empty clone of a repo, there's nothing that would convince hg update to avoid starting off by pulling all of the subrepos.
I should point out that it is crucial to retain the ability to easily sync to the head revision after creating such a clone.
This should do what you want:
REM Take a new clone, but do not update working directory
hg clone --noupdate %REPO_PATH% %DESTINATION%
REM Update working directory but exclude the certain subprojects
hg revert --all --rev %BRANCH% --exclude %SUBREPO_PATH_1% --exclude %SUBREPO_PATH_2%
This answer may add more than the question required, but provides some valuable notes on working with Mercurial when you can't update do to a bad subrepository path or revision.
Step 1: Clone the repository without any updates
hg clone --noupdate source_repository destination_repository
Step 2: Use revert to get the right files
hg revert --all --rev revision_number --exclude subrepo_1 --exclude subrepo_2 ...
At this point, you have a new changeset; you may need to make sure the parent revision is correct. When I did this, my new changeset's parent was changeset 0. To fix this I had to set the parent changeset AND switch branches (since my changeset was on a different branch).
Step 3: Change the parent of the current changes
hg debugsetparents revision_number
hg branch branch_name
That should do it.
Found a hacky way. It still requires all subrepos to be checked out once, but afterwards they can be deleted.
Clone the whole lot, including subrepos. No way around this.
Delete subrepos
hg remove .hgsub
I tried to convince Mercurial to hg remove .hgsub before the subrepos are cloned, but the best I got is not removing .hgsub: file is untracked.
If you have a subrepo, a working directory must include some version of that subrepo. That version may be a fixed older revision if specified, or the tip if not.
You cannot update your repo without getting the subrepos; if you had a complete working dir without them, you shouldn't be using subrepos - use truly external repos instead.
If your subrepos are pegged against a certain remote version, then updates after the first will not trigger a subrepo update - they're already up-to-date. But for the initial creation of the working directory, you will have to do a remote pull.
You can trick Mercurial by munging the hgsubstate file. But really, your model and the conceptual model differ, so you're probably not a good match for subrepos if this is a concern.
edit: If you find yourself cloning and then updating to the tip many times, try using local branches or mq instead. That way you only have to do the initial clone once.