I started a named branch several months ago which I then abandoned. Now I want to "restart" it. Specifically, I want to bring it up to the latest version of default and start working on it again.
I tried updating to the branch, and then reverting it to default,
hg revert -a -r default
But when I swap back and forth between this branch and the actual default I see 112 files have changed, so clearly they are not the same.
I ended up closing the branch, updating to default, force-switching back to my named branch again, and then force pushed (because it creates a new head).
Now my named branch is the same as default, but I have this short dead branch in my history now.
My questions are:
What was hg reverting to default doing? Was it reverting to the closest default ancestor rather than the tip of default? Even when I tried reverting to the tip via an explicit changeset, the two branches ended up different.
What is the "proper" way to do this?
What was hg reverting to default doing?
For your (really bad )syntax:
Using the -r/--rev or -d/--date options, revert the given files or directories to their states as of a specific revision
i.e to the state of latest ancestor in default branch for all files in repo
I see 112 files have changed, so clearly they are not the same
Wrong assumption
Because revert does not change the working directory parents, this will cause these files to appear modified.
I.e you must commit this modified Working Directory and diff (for testing) heads of branches after it only
What is the "proper" way to do this?
Proper ways is
If you want to save branch-specific changes and only update with latest changes
Update to the head of abandoned branch
Merge default branch to your branch
Resolve all (if any) conflicts
Commit mergeset
If you want to have empty branch only and remove all changes from it
Backout all changesets from branch
Commit backout-changeset
Merge default to branch
Related
I am on the default branch, but some old commits are said by mercurial to be other default heads.
I would like to push a commit, but I can't because otherwise I would have to push other default heads which would be wrong.
How can I make the situation clean? I assume I have to get reed of these additional default heads and so that I again push my work. Is there a safe way to do it?
First piece of advice is to backup you repo so that if something goes wrong, you have a return path.
You will need to determine if the other heads are important or if they can be thrown away. You can list the heads with:
hg heads
if the other heads are throwaways, you can use the hg strip command. Some caution is
needed here. If you created a anonymous branch (the head in question) and later merged
it back to your default (or other branch), deleting it will cause any changed after the merge to also be removed.
You should spend some time reviewing: hg log -G (or one of the many graphical interfaces) and determine if this is going to be an issue.
If it is an orphan branch (head) you can use:
hg strip changeset-id
I recently grafted a changeset in a development branch into the default branch. After that, my changes went in default as desired.
But unexpectedly, there were a lot of metadata level changeset changes went in with that checkin. To elaborate,
Several files that were present only in my development branch and not in default branch were marked as removed in default.
Several extra lines in certain files that were present only in my development branch and not in the default branch were marked as removed in default.
Mercurial has marked certain files and lines that are not actually present in default as removed files and lines in the default branch.
Due to this, when I try to merge again with default, mercurial marks those files and lines are removed from default and it tries to remove the same from my branch.
I tried backout to revert my problematic commit alone. Unfortunately, backout only changes the source code lines modified during checkin, but doesn't remove the metadata marking of removing the unavailable files and lines.
Is there anyway to undo the commit metadata level changes that happened undesirably? Any help much appreciated.
Thanks.
If you have a bad commit and just want to forget it ever happened, and that commit has no descendants, you can just do hg strip to remove it from history entirely (requires strip extension).
If the commit does have descendants, you can use hg histedit (requires histedit extension) to drop the changesets you don't want to keep.
Both these solutions involve editing history, which is risky if you've distributed the bad commit publicly. You will have to coordinate with everyone who may have pulled the bad commit or any of its descendants, which isn't always possible (e.g. in an open source environment). You will also need to redo these changes server-side, since Mercurial's push --force is not like Git's push --force.
If you don't want to edit history, you can graft the descendants of the bad commit onto the last known good ancestor (e.g. hg up good_ancestor; hg graft 'bad_commit:: - bad_commit'), then do hg commit --close-branch at the bad head(s). Be sure to leave an informative commit message on the close-branch commit, so that other developers will know where to rebase anything that descends from the bad commit.
In Mercurial , How to clone from a specific revision to the last one using ?
For example repo A have one line history from changeset 0 to changeset 100. and I want to clone A to my local repo from changeset 90 to last one (100).
Looking through the help, I noticed the -r flag but that only clone 1 specific changeset.
And if there is no way to do it can somebody explain why its not implemented ? its considered a bad thing to do ?
Thanks.
You can't.
The current state of the project is all changesets from the beginning of time up until the specific changeset, you cannot prune older changesets without rewriting the history of the repository to permanently get rid of them. This will also make the repository incompatible with the original that contains the old history.
In short, you will have to do one of the following:
Prune the old history, permanently getting rid of it, which will make it impossible to push/pull with original clones that still has that history
Live with the history
The parameters to the clone command that specifies revsets thus only allow you to set an upper limit. This may allow you to avoid whole branches, if they aren't merged into the branch you end up cloning, but the clone command will always clone everything from the beginning of time.
For every changeset you clone, every predecessor will be cloned as well, and this cannot be avoided.
I sometimes but not always end up with two heads on my default branch. The sequence of events is something like:
hg pull
hg update -C default
hg branch mybranch
hg merge default //merge in default
hg commit -m"merged mybranch into default"
hg heads -default //shows 2 heads
hg push --branch default //won't let ne. create 2 heads
The 'rival' head appears to be a changeset committed to default earlier in the day.
What I don't understand is why this happens sometimes and not other times.
The explanation I am usually offered is that the other guy pushed a change after I did a pull (my first action in the list above). But I think this happens in other cases e.g. when he pushed his changeset before I started.
I would have thought that when I pull default with his commit I get default with one head. My merge/commit should just create a new head after that. Why does it create a second head?
First of all, this is a totally normal situation. It's not a problem, or an error, or something to be avoided -- it's how a DVCS works.
In brief: you get two heads whenever two people start working from the same commit and do different things. It doesn't matter if they do it in their own (named) branch (as you're doing above) or on default. Once you merge your work back to default and someone else has done work on default you've got two heads and someone has to merge. It's just how things are.
Before you push do a hg pull and then a hg merge and you'll integrate your work with yours, by creating a new merge commit, with two parents -- your work and their work -- and then you push and you'll not see that warning.
Incidentally, you might want to check out the bookmarks feature. It's better suited for per-feature branches like you appear to be doing above than the named branches you're using, but it in no way saves you from having to deal with multiple heads.
check state of repository immediately after pull (pull can bring new head in default for you) with hg heads
hg branch without commit do nothing (you haven't mybranch)
Even if you'll create mybranch and merge it with default's tip (according to your syntax), it will not eliminate 2-nd head in default
Let say I had a feature branch called feature_x that was worked on, then changesets cherry-picked and transplanted to default, then the branch was closed. Not the best flow, but it's Mercurial, so there is no way of changing the history.
Now I'm going to work again on the feature X, and I feel reusing feature_x branch would be least confusing. However, if I reopen that branch and merge default to it, I've got two problems. First merge conflicts, second changes that were modified in that branch, but never merged into default. So what I'd like to have is clean slate, branch feature_x, but with exact copy of what's currently in the default. Is there a cleaner way of doing that, than creating new branch which will shadow the name?
I think your best bet is to start a new branch off of the current tip of default called feature_x2 or feature_y and leave the past in the past.
But here are some other options:
Is the old feature_x branch confined locally to your repo only or was it pushed? If the former, you could hg strip it and start the branch again at the current default.
If the feature_x name is really, really important, you could do the merge default into it using the internal merge tools and force it to reflect the default branch exactly by doing
hg merge -r default --tool internal:other
Or you could just commit a (file system) copy of default on top of the tip of branch_x. Then you could continue on that branch along your merry way.
I don't know if 2. or 3. will cause strange merge issues down the road. I would test to see if the merge back over to default (or another graft?) could cause issues later.