I have done some local commits.
But I want to push the most recent ones like 4977 and 4978 excluding the previous ones.
4948 local commit 1 is the ancestor of all commits
Can some one tell how do we do that in HG
4978 local commit 4
|
|
|
4977 local commit 3
|
|
|
4976 local commit 2
|
|
|
4948 local commit 1
Mercurial repositories are intended to have immutable histories, so out of the box this is not possible. However, there are workarounds for this.
Possibly the easiest way to achieve this would be with the histedit extension. You would need to enable it by modifying your .hgrc (or mercurial.ini) with the following
[extensions]
histedit =
Then you can run the histedit subcommand from the command line and tell it to look back as far as the changeset you're concerned about...
hg histedit 4948
This will pop up a text editor with the word pick next to each changeset. Change pick to drop for the changeset you don't want any more, save, and exit, and the problem changeset will be gone.
Note that this will remove the changeset from your local repo, in addition to prevent it being pushed to the remote!
You cannot push a commit with out pushing all the ancestor commits as well. However, you can "fold"/"collapse"/"squash" commits together to get rid of the ancestor commits you don't like. You use the standard histedit extension for this.
Simply run
$ histedit 4948
and you will see an editor open up. That edit contains a file that will serve as the instructions for histedit. By default all changesets are left unchanged, but you can change the keyword at the beginning of the lines to change this. Also, you can reorder the lines to reorder the corresponding commits.
Changing the keyword in the beginning of a line to fold will tell histedit to combine the commit with the previous commit. That way you can change your history to
4978 local commit 4
|
|
|
4977 local commit 3
|
|
|
4948 local commit 1
and thus "fold" the changes you made in your local commit 2 into local commit 3.
Related
I have repository with wrong branching. Branches was used like tag for commit message, showing related part of project (eg data, search - like features). No merging was used. Each next commit, if it is about other feature than prev, just reopens branch with desired name.
It looks like
o changeset: 717
| branch: default
|
o changeset: 523
| branch: search
|
o changeset: 357
| branch: data
|
o changeset: 397
| branch: data
|
o changeset: 789
| branch: default
Whats the right way to stop that ugliness?
Update to each branch-head and merge with last commit consequentially? But there nothing to merge actually.
Or update to each head, commit with "close branch", update to next head ... and at last update to default?
Firstly, as Aaron pointed out, and assuming these are misunderstandings by the commiters, you will need to teach the others working on that repo when its appropriate ( by your definition of appropriate ) to create named branches, and when it isn't. I imagine that would solve most of your problems.
If you want to bring everything back in line, and the branches are currently open, you can close each branch and then merge them into default. If you don't merge after closing, you will have a 'dangling' commit in your history graph, but that may or may not matter to you. Also, if you only have 1 'active' branch, which you can check with
hg branches
then all the commits are currently merged into that active branch, and you may only need to merge that branch into default to bring things in line. However you may still want to close the inactive branches, which will leave you with dangling commits if you don't merge them after closing.
If you want to avoid having commits with branchnames, you could look at using bookmarks, which are sort of an amalgamation of branching and tagging.
If you want to minimise branching ( even anonymous branching ) on your repo, you could use rebase, which is a built in extension that you have to enable. You can use the rebase switch when pulling someone else's changes, to automatically move your commits after the commits you are pulling in and make the history linear. You cannot do this once your commits have already been pulled or pushed elsewhere however ( well, you could, but it would make things very complicated depending on what happens with your pulled commits ). However using rebase would depend on how you feel about keeping accurate history.
To clean up the existing repo could be a bit of a mission. You could use rebase to move all the commits to a common branch, such as default, however since it changes your history it will no longer be 'compatible' with the existing clones of that repo. So you would have to use rebase to alter your history, and then have everyone ( including servers ) reclone the altered repo and trash the old one ( they cannot even pull any outstand commits from the old one to the altered repo ).
From the look of the history (just one line), people really just gave each commit a different branch name without actually ever doing any work on two different branches at the same time.
While I haven't seen this before, it's a interesting and clean way to sort changesets into features without creating an ugly history.
As for "stopping" this, just stop reopen branches. There is nothing that you need to do to "clean" the history since there aren't actually any heads which need merging. Therefore, Mercurial will tell you "nothing to merge" if you check out default and say hg merge search.
We are faced with a situation where we are maintaining two code bases in the same repository. The folder structure looks like this:
/WebRoot/
In our default branch the /WebRoot/ is very different from the /WebRoot/ in the Stable branch. The goal is to move /WebRoot/ from the Stable branch to /WebRoot/ in default branch. And the current default /WebRoot/ will become /WebRootX/. So in the end, all code will be in default and we won't have to switch back and forth between default and Stable branches when making changes in the two different code bases.
| | |
| | |
| --------
| | QA
| |
-------|
| Stable
|
default
I'm thinking that we have to use hg convert to move the Stable code out to a different (temp) repository. Then rename the default WebRoot to WebRootX. Then import the Stable /WebRoot/ folder back in.
I have done several tests and I'm not getting the desired results. I have tried using hg convert with the branchmap ("Stable default") to get the Stable branch out to a temp repository, but that's not working. I'm seeing code from default in there.
What is the best way to accomplish this?
Before trying anything below first back up your repo.
Now you can try this: in the default branch, rename WebRoot to WebRootX. Commit this change.
Still in the default branch, merge in the stable branch using the internal:fail merge tool (what git calls a merge strategy):
hg merge --tool internal:fail stable
At this point, your working copy is in a state that, if committed, Mercurial will accept as a successful merge. But before you commit, you want to tell Mercurial to revert the entire WebRoot directory structure to its state in the stable branch, while at the same time not reverting anything that in the WebRootX directory structure:
hg revert --all -r stable -IWebRoot* -XWebRootX*
At this point you should have the WebRootX directory structure as it was in the default branch, while at the same time having the WebRoot directory structure as it was in the stable branch, and also preserving both their histories.
I have to warn you though I just roughly tested this out in a dummy repo and I'm not sure what results you'll get in a 'real' repo.
Some ideas from here.
This question already has answers here:
Is there any way to delete local commits in Mercurial?
(10 answers)
Closed 8 years ago.
I've used Git in the past and I'm a Hg noob:
I have following repository structure:
o [> default] commit A
|
o commit B
.
.
.
o <a-tag]
|
I've updated to the commit with the a-tag and committed a few other commits. Now I have
o [> default] commit C
|
o commit D
|
| o [default] commit A
| |
| o commit B
| .
| .
| .
| /
o <a-tag]
|
Now (before pushing) I realize that I had my commits commit C and commit D based on the wrong commit. How can I go back to the initial state (without having to re-clone the repository) dropping these commits commit C and commit D (pendant to git reset --hard a-tag)?
You can use 'strip' to permanently delete commits and all it's descendants. In your case you need to specify the id of "D" revision:
hg strip -r D
Note: mq extension must be turned on:
[extensions]
mq=
Mercurial backups bundles of the stripped changesets in .hg/strip-backup so this operation is rather safe.
You say without cloning, and I'll get to that but first let me point out that doing this:
cd ..
hg clone -r -2 yourrepo yournewrepo
is an instantaneous action that gets you a new clone, locally, without the last two commits in your old repo. Because it's a local clone it uses hardlinks (even on Windows) so the repository takes up no additional diskspace.
That is the classic Mercurial solution. Mercurial was built with the idea of an immutable history. If there's something in the history you regret you commit its inverse (which is what backout does), so the history shows the error and its correction -- like a scientists log book. If you can't/couldn't abide having it in history you'd do a clone that excludes it like I showed above.
Not everyone can be quite so... hardcore... about their history, so lots of extensions have shown up that will modify history but they have to be specifically enabled. In your case the rebase extension, which you already have installed (it comes with Mercurial now), will do exactly what you want. You just need to enable it in your ~/.hgrc and then reparent D onto A. If you really just want C gone the strip command from the mq extension will do that. It also ships with Mercurial.
I would just clone from the appropriate point and delete the old repo.
Without cloning consider hg backout to undo first C and then D, or, if this is your ultimate goal hg rebase to move both C and D to the commit A point.
Backout C + backout D will remove these 2 commits, but add additional 3 (backout+backout+merge). "Clean" remove from history may be
Histedit extension ("drop" command)
MQ extension (convert changeset to mq-patches /first steps/ and drop mq-queue)
If you want only change wrong parent to correct, you have to use rebase, as #chill mentioned
My coworker accidentally made two commits in the default branch instead of creating new his own development branch.
How can I change this situation and moves these two commits to a new branch?
Imagine the following scenario:
D
|
C
| "I want to move C and D here"
B/
|
A
Steps:
hg update B
hg branch "mybranch"
hg commit --message "Create my branch"
hg update mybranch
hg graft -r C
hg graft -r D
hg strip -r C (this should be the revision C had originally)
The strip command is provided by an extension that you need to enable. You can follow a guide on how to enable it on the Mercurial Wiki.
hg update default
A major question
Have the accidental commits reached other repositories or is it just in his own? If so, you can skip to the section below 'Maybe the cat is still in the bag' otherwise you may have a fair bit of work to do.
You are not alone
See here for more discussion on how to correct the problem elsewhere on Stack Overflow. What is described is the 'proper' way to to it
export a patch
create the branch
import the patch
delete the earlier commits.
Maybe the cat is still in the bag
If the changes are only in the local copy, then a simpler solution is to
create the new branch
switch to it
merge the changes onto that either with your fav merge tool (go Meld) or with hg graft
use the hg strip command to delete the changes on the old brach
push the changes to the world
pretend like nothing ever happened, whistle a happy tune ...
The two answers above are both correct but, assuming one has not yet pushed the commits, there's a third way.
I just successfully used the rebase command to move a string of commits to a topic branch I had forgotten to create in the first place.
I first updated to the revision from which I wanted to create the branch on which my commmits were supposed to be, then I rebased the earliest of my commits from the wrong branch on this new one and ta-da, done.
Takes more time to explain it than to do it with TortoiseHg or even the command line, really.
I would like to know why the following pattern is not possible.
Having created a local feature branch (minor_feature - not intended to be shared with the world) I would like to rebase the work on it on to the tip of a well known branch (stable). However I have discovered that rebase finds nothing to be rebased in the case where stable has not progressed since branching away from it.
I appreciate that this breaks the rule that the destination of rebase can not be an ancestor of the source but can't work out why this should be prohibited in the simple case shown. I also understand that, branches aside, the topology would not actually change during the rebase. But given that the branch names are indeed significant to the topology, it only seems to be a special case in that stable has no further revisions commited to it. With a single extra revision on the tip of stable (say pulled in from elsewhere) I can of course perform the rebase
o branch:minor_feature
| rev:4
| changeset:746d8191aa5d
|
o branch:minor_feature
| rev:3
| changeset:520f565ba7f2
|
# branch:stable
| rev:2
| changeset:64e7c753c090
|
o branch:stable
| rev:1
| changeset:3dc55a5c9971
|
o branch:stable
rev:0
changeset:fbf1f426945c
$hg rebase -b minor_feature
nothing to rebase
--
Thanks
Chris Gorman
Rebase is strictly for changing ancestry of changesets. As you've observed, you're not changing ancestry here. Branches aren't included in the ancestry computation.
I'm not 100% sure what you're trying to accomplish. If it's to effectively remove the branch, then as long as you haven't pushed, you can likely use the MQ extension. Import the changesets, pop all. Ensure you're updated to the stable branch (which it should be by default), and push them all back on.
They should now all be on the stable branch.
You can do this with the convert extension. You would use a branchmap to rebase minor_feature to default. That file (we'll call it alldefault) would look something like this:
minor_branch default
Then the command would just be:
$ hg convert --branchmap alldefault oldrepo newrepo
When it finishes, newrepo will have the named branch "rebased" on top of the default branch.