Push Mercurial subrepo to the same path as its parent - mercurial

Is there any way to configure Mercurial to push a subrepository to the same path specified when pushing its parent?
Say we have a parent repo with a subrepo, and the subrepo also has its own subrepo:
A
- B
- - C
Now, in each of A, B, and C we have alternate paths specified:
A .hg/hgrc
[paths]
default = http://path.to.default/A
devMachine = ssh://user#dev.machine/A
B .hg/hgrc
[paths]
default = http://path.to.default/B
devMachine = ssh://user#dev.machine/A/B
C .hg/hgrc
[paths]
default = http://path.to.default/C
devMachine = ssh://user#dev.machine/A/B/C
If I have unpublished changesets in A, B, and C, that I do not want to push to the central repository, but I DO want to push them between my Work & Home dev machines, is there any way I can set up Mercurial such that when I do hg push devMachine it will push B and C to devMachine as well, rather than pushing A to devMachine and pushing both B and C to default?
What I have been doing thus far is setting the new-commit phase to secret and doing:
$ cd A/B/C
A/B/C$ hg phase -d
A/B/C$ hg push devMachine
A/B/C$ hg phase -sf
A/B/C$ cd ..
A/B$ hg phase -d
A/B$ hg push devMachine
A/B$ hg phase -sf
A/B$ cd ..
A$ hg phase -d
A$ hg push devMachine
A$ hg phase -sf
For obvious reasons this is less than optimal. It would be much nicer if doing A$ hg push devMachine would recursively push all subrepos to the devMachine path (given that it has been defined in .hg/hgrc of course).
I know I could script this pretty easily. I'm just curious if Mercurial has something built-in that will do this that I haven't been able to find.

I DO want to push them between my Work & Home dev machines, is there
any way I can set up Mercurial such that when I do hg push devMachine
it will push B and C to devMachine as well, rather than pushing A to
devMachine and pushing both B and C to default?
Well, it works this way using TortoiseHg. The hgrc path section was set the same way you described. But the path alias was not being used in the call.
Log output was: hg push some-real-absolute-path
Instead of hg push devMachine, try hg push ssh://user#dev.machine/A
About the phases, in every repository of the Work(and/or Home) machine, add to hgrc:
[phases]
publish = False
Then commits will change to public phase, only when pushing to the central repository.
I advise to NOT use:
[phases]
new-commit = secret
Secret phase doesn't mix that well in subrepositories. I would only use it in the root repository.

Related

hg-git: `unknown revision` with one git clone, ok with another

Closed: I started a hg clone... by error in the git repository and this created an empty hg repository. So hggit checks the differences with the empty hg repo and not the git conversion.
$ hg incoming -r branchname_bkm G1
comparing with /home/xxxx/src
abort: unknown revision 'branchname_bkm'
_bkm is the suffix I use between git branches and hg bookmarks.
I have a mercurial repository for long time (named HG0).
I converted it to git using the hggit extension, pushed it to gitlab.
I usually develop in the git repo (named G1) but our official repo is still mercurial.
When needed, I import a git branch (as bookmarks) this way:
update the hg-git map:
cd HG0
hg pull
hg update main_bkm # bookmark on default == main
hg git-cleanup
hg outgoing G1
import git branch:
hg in -r <branchname> G1
It worked perfectly during months.
For about 2 weeks, hg out shows me all the changesets, not only the new ones and hg in returns unknown revision!
I created a new git clone G2 from gitlab. hg out G2 is correct and only shows few revs as expected.
I could exchange my git branch from G1 to G2 and get it in HG0, ok.
How can I "re-synchronize" my hg repo with G1?
git-cleanup does not change anything.
I even tried to entirely rebuild the embedded .hg/git (~2 hours), no change.
If I grep a revision shown by hg out G1 in .hg/git-mapfile, it corresponds to the related revision in G1...
May git garbage collection process "hides" something used to identify the repo?
Thanks in advance.

mercurial push certain revision

I have searched here, but haven't found any question related to this. I got a problem like this in mercurial:
I manage open source project in bitbucket, so i have clone of the source code in my local. But I also using that project for my own live site, so I made 2 clone of bitbucket repo
Bitbucket Repo
|
==local_clone1
|
==local_clone2-> commit1 => commit2 => commit3
(personalization) (bug fix) (add feature)
The question is, I want to push commit2 and commit3 back to local_clone1, so later on I can push to Bitbucket repo. But don't want to push commit1, since it has my personal data.
Wondering how we do that in mercurial?
This can be done without too much difficulty in this case. See Removing history in the Mercurial guide for more information.
Here's the basics of what you'll need to do:
Go to local_clone2
Get the revision number (hg tip will show you) from the current number. We'll call it 731.
hg export 730-731 > ../local_clone1/changes.diff (or wherever you like)
Go to local_clone1
hg import changes.diff
You may need to edit things manually; refer to that guide for more info in that case.
Here are a couple of options:
backout
Given a history constructed as:
hg init db
cd db
echo >file1
hg ci -Am clone # rev 0
echo >file2
hg ci -Am personalization # rev 1
echo >file3
hg ci -Am bugfix # rev 2
echo >file4
hg ci -Am feature # rev 3 <tip>
Then if the current working directory is the tip, the following commands will "undo" the personalization revision:
hg backout 1
hg ci -m backout
The advantage is history remains immutable, but shows the addition and backout of the personalization changeset.
Mercurial Queues
With the mq extension, history can be edited to remove a changeset:
hg qimport -r 1:3 # convert changesets 1-3 to patches
hg qpop -a # remove all patches (can't delete an applied patch)
hg qdel 1.diff # delete rev 1's patch
hg qpush -a # reapply remaining patches
hg qfin -a # convert all applied patches back to changesets.
The advantage is the personalization changeset disappears. The disadvantage is the changeset hashes change due to the history edit, so this should never be done to changesets that have already been pushed to others. There is also the risk of a mistake editing history.

With Mercurial, if there are two local clones, can you push from one branch to another branch?

If there are two branches, and I have been doing work on the default branch, I think one way to push to the foo branch of the other clone is
cd ~/development/clone2
hg up default
hg pull ~/developmet/clone1
hg up foo
hg merge default
or
cd ~/development/clone1
hg up default
hg push ~/developmet/clone2
cd ~/development/clone2
hg up foo
hg merge default
These 2 methods work exactly the same? (one is a pull, one is a push).
Is there an easier way to directly push clone1's default branch to clone2's foo branch? thanks.
(I use clone 1 to see all the changes I have done (without seeing anybody else's changes), and use clone2 to merge and integrate with other team members)
You can always push and pull a single revision and all of it ancestors using:
hg push -r revision ~/development/clone1
or
hg pull -r revision ~/development/clone2
There's no way to "push to another branch" because you'll always have to merge the two different branches manually
Both methods you described work exactly the same, but the first one is recommended (Always do the merge work in your clone, not the integration repository or somebody else's clone)
Maybe is an intentional omission but in both examples you have to commit the result of the merge and in the first example you have to push the merge changeset back to clone2
So in ~/development/clone1 do:
hg up default
hg pull -u ~/development/clone2
hg up foo
hg merge default
hg ci -m 'merged default into foo'
hg push ~/development/clone2
If you do this a lot you may consider adding this lines to your ~/development/clone1/.hg/hgrc file
[paths]
default = ~/development/clone2
This way you can omit the repository path when you're pulling and pushing from the integration repository

How to apply a collapsed revisions patch to trunk in Mercurial?

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

How to move some changeset to a new branch in mercurial

I want to move a changeset from one branch to another. Basically, I currently have:
A -> B -> C -> D # default branch
And I want:
A # default branch
\-> B -> C -> D # some_new_branch
Where some_new_branch does not exist yet. I am used to git, so I guess there is a simple "mercurial" way I am missing.
One way is to export a patch for B,C,D; update to A; branch; apply patch:
hg export -o patch B C D
hg update A
hg branch branchname
hg import patch
To remove B,C,D from the default branch, use the mq extension's strip command.
Sounds a bit like a cherry-pick operation in git. The Transplant Extension may be what you're looking for.
With Mercurial Queue:
# mark revisions as draft in case they were already shared
#hg phase --draft --force B:D
# make changesets a patch queue commits
# (patches are stored .hg/patches)
hg qimport -r B:D
# pop changesets from current branch
hg qpop -a
#
hg branch some_new_branch
# push changesets to new branch
hg qpush -a
# and make them commits
hg qfinish -a
Without comments:
hg qimport -r B:D
hg qpop -a
hg branch some_new_branch
hg qpush -a
hg qfinish -a
Alternative to transplant or patch, you could use graft.
hg update A
hg branch branchname
hg graft -D "B:D"
hg strip B
Note that changing history is bad practice. You should strip only if you haven't pushed yet. Otherwise, you could still backout your changes.