Replace master with a branch - mercurial

I need to replace the contents of master with the contents of a branch. I can find details on how to do this in Git, but nothing for Mercurial.
Example Q for Git
Replacing master with another branch
My setup is
master
newbranch
I want the 'master' to be identical to 'newbranch

The basic choice you have is "rebase or merge": https://blog.sourcetreeapp.com/2012/08/21/merge-or-rebase/
Here on SO, a helpful Q&A is at:
Make another branch default?
The remainder of this response borrows from that page.
If you want to close the "feature-branch":
$ hg checkout default
$ hg merge feature-branch
$ hg commit
$ hg checkout feature-branch
$ hg commit --close-branch
The simplicity of the revert/commit approach mentioned there also has much to recommend it:
hg revert --all --rev ${1}
hg commit -m "Restoring branch ${1} as default"
where ${1} is (for example) the name of the relevant branch.

Doesn't the first approach assume there are no conflicts between the "default" and "feature branch"? When you desire to replace code, the assumption is that there ARE conflicts, and all should be resolved treating the "feature branch" as authoritative.

Related

Mercurial: Switch working directory to branch without losing changes?

Let's say that I have a named branch 'B1' which I'm doing feature development on.
I am at a good stopping point before a demo though not done with the feature so I:
hg up default
hg merge B1
hg ci -m "merged in feature drop"
hg push
Now I continue working for a half an hour or so and go to commit only to realize that I forgot to update back to B1 and that my current working directory is on default - uhoh. In theory I should be able to just mark my working directory parent as the tip of B1 - is there an easy way to do this?
I could of course commit, update back to B1, and merge my changes back, but then there's an unstable changeset in default and this happens often enough to me that I would like a real solution.
Two ways. First, the obvious way:
hg diff > foo
hg up -C b1
hg import --no-commit foo
rm foo
Second, the magical way:
hg up -r 'ancestor(., b1)' # take working dir back to the fork point
hg up b1 # take it forward to the branch head
This way involves merges. Depending on how much your branches have diverged, this may be painless. Or it may be complicated, and you may make a mess of your changes that you haven't saved anywhere. Which is why even magicians like myself prefer to do it the first way.
I would use the shelve extension. I think it’s distributed along with TortoiseHg, you can also use it from the UI:
hg shelve --all
hg up B1
hg unshelve
Rebase extension allow you to change parent for any commit for wrongly commited changeset.
If you want just change branch for future commit - MQ (as mentioned) or Shelve
Typically for this sort of dynamic approach, I favor mercurial queues.
In your situation, what I would do would be to create a patch on default with the changes, pop the patch off, switch over to B1, and apply the patch.
It goes something like:
hg qnew OOPSPATCH
hg qrefresh
hg qpop
hg up B1
hg qpush
<hack hack>
hg qrefresh
hg qfinish
All you need is simple hg up -m B1
From hg up --help:
options:
…
-m --merge merge uncommitted changes
…

Make another branch default?

I have a Mercurial repo at Bitbucket and on my local machine, both are mirrors, up to date. I created a feature branch, reflected in both repos. I did all my work in the feature branch.
The feature branch is now complete and I want to now make it the default for the main repo and my local copy. I don't really care about the default branch, enough work has gone into the feature branch that all I want to do is designate it as the new default.
I don't think I want to merge nor should I? How can I do this so both local and remote don't get confused?
Just merge feature-branch into default then close feature-branch:
$ hg checkout default
$ hg merge feature-branch
$ hg commit
$ hg checkout feature-branch
$ hg commit --close-branch
There is no more clean and sensible way (that I'm aware of) to “make feature-branch the default”.
One thing that wouldn't be as nice, but you could do, is to make a commit to default on top of feature-branch:
$ hg checkout feature-branch
$ hg branch default
$ hg commit
But this would leave two heads in the default branch, which is suboptimal.
Since Mercurial 2.4, you can create an bookmark called # and Mercurial will checkout that revision new clones.
However, I would still try to stick with using default as the branch where the main development takes place. Doing so will cause the least amount of surprise for developers already used to Mercurial — the wiki describes the standard way to use branches in Mercurial.
If you follow the conventional advice of using default as the main branch for development, then you should close your feature branch before you merge it back:
$ hg update feature-branch
$ hg commit --close-branch -m "Feature done, merging into default branch"
$ hg update default
$ hg merge feature-branch
$ hg commit
If you haven't done any work at all on the default branch since your started the feature branch, then this merge will be trivial and have no conflicts. Otherwise you'll have to resolve conflicts. If you're sure you want to keep everything from the feature branch, then you can do
$ hg merge --noninteractive --tool internal:local feature-branch
$ hg revert --all --rev feature-branch
instead of just hg merge above. That will make sure that the new commit on default look exactly like the last commit on feature-branch.
I succeded without merging by closing the default branch.
in my development repository working directory:
$ hg update default
$ hg commit --close
then my development branch became the new default branch.
But i do not know the rules for why my development branch was choosen
as the new default.
i think it is because it was my tip ?
(or maybe last changed branch? (tip?))
I also think that you have to repeat that next time.
Because i think my chosen branch name was "overwritten" by the 'default' name.
It would be nice to have branch name.
dev-projectname-version.x=default
regards
I wanted to do just what you described and hunted around until I found an answer which uses the revert command to do just what you describe. Here is the code I used:
hg revert --all --rev ${1}
hg commit -m "Restoring branch ${1} as default"
where ${1} is the number of the revision or the name of the branch. These two lines are actually part of a bash script, but they work fine on their own if you want to do it manually.
This is useful if you need to add a hot fix to a release branch, but need to build from default (until we get our CI tools right and able to build from branches and later do away with release branches as well).

In Mercurial how do I extract a single file's changes from a Changeset to apply to another branch?

I have a large commit of many files on one branch, I need to transfer the modifications of a single file in that changeset to another branch. How can I do this? I am mostly using TortoiseHg but commandline solutions are also fine.
If I go to the changeset in TortoiseHg and select the file I can see the diffs I want to transfer, but not a way to actually apply them.
You can get the patch for just that file using:
hg log -r THEREVISIONWITHLOTSOFCHANGES -p -I path/to/justthatfile > justthatfile.patch
which you can then import on whatever branch you want by doing:
hg update anotherbranch
hg import --no-commit justthatfile.patch
hg commit
The most basic solution is to dump the patch of the file, apply it to the current working revision, and commit it (assuming you're at the root of the repository):
$ hg up <revision-to-apply-the-patch-to>
$ hg diff -c <revision-containing-the-patch> <files-to-include> | patch -p0
$ hg ci -m "Transplanting selected changes from <revision-contain...>"
The drawback of this method is that it isn't very obvious what you've done from a revision history perspective. A good commit message helps here, but the history graph gives no hint about the process of transplanting some changes. In that case merging and reverting may be a better solution:
$ hg up <revision-to-apply-the-patch-to>
$ hg merge -r <revision-containing-the-patch>
$ hg revert --no-backup <files-to-exclude>
$ hg ci -m "Merge in changes of <files-to-include>"
Probably there are more solutions to do this -- these two came to my mind first.

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.

Can't branch a single file with Mercurial?

is this possible with Mercurial? and which Version Control system can do this besides Clearcase?
David is correct that you can't have a branch that exists on only a single file, but it's worth pointing out that people often have branches that alter only a single file. Since the branch metadata is stored in the changeset, and since the changeset contains only a delta (change), having a branch that alters only a single files is nearly instantanous to create, update, commit, and merge, plus it takes up almost no space on disk.
Resultingly, it's a very common way to handle per-customer configurations. Keep the tiny change for them in a branch, and merge from main, where development happened, into that branch, whenever you want to update their deployment.
How you could use MQ:
$ hg qnew -m "Changes for client0" client0
... change the file ...
$ hg qref # update the client0 patch with the changes
$ hg qpop # pop the changes off the queue stack
... develop like normal ...
... client0 asks for a build ...
$ hg qpu # apply client0's patch
$ make release
$ hg qpop
It would get a bit finicky if you've got to deal with a lot of clients… But it may be worth considering.
The other thing you could do, of course, is just commit a bunch of .diff files:
... make changes for client 0 ...
$ hg diff > client0.diff
$ hg revert --all
$ hg add client0.diff
$ hg ci -m "Adding client0 changes"
... develop ...
... client0 asks for a build ...
$ patch -p1 < client0.diff
$ make release
$ hg revert --all
No, it's not possible. A branch in Mercurial is a snapshot of the entire repository state.
You could do it with CVS, though, as CVS tracks changes on a per-file basis :)