How do I remove a single changeset (which is not a head) from a repository?
hg strip doesn't work because I don't wanna remove the descendants.
hg rebase on a head and then hg strip would work, but I can't rebase on a descendent. (that yields an error)
My changeset is not related to anything else (it's just a bunch of file adds I shouldn't have made), so it should be easy to remove without problems. Also, my repository in fact has a linear history (each changeset only has one child and in particular, there's only one head).
Background
I'm using hgsubversion and either it or my SVN server crash when I try to push a commit that touches any file that has umlauts in its name. I accidentally added such a file and then did some other work on top of it. Now the offending commit needs to be removed.
As ngoldbaum implied in a comment, strip removes descendants, not ancestors. If there are no descendants you're OK. (Watch out, though: descendants in another branch will be stripped!)
If your issue is that the commit has descendants, you can still use hg histedit to remove it while keeping its descendants.
Related
I'm in the process of doing a merge, and I'm ready to commit at this point but my commit dialog in TortoiseHg is showing many files as modified but when I diff to parents it says all files are binary equal.
I do not have and have never had the eol extension enabled.
Revert changes nothing, the file is still registering as modified.
hg parents shows two parents for the file.
hg stat shows the file as modified, e.g.
c:\Projects\MyProject>hg stat Authorization\AuthorityGroups.cs
M Authorization\AuthorityGroups.cs
hg diff --git shows nothing, e.g.
c:\Projects\MyProject>hg diff --git Authorization\AuthorityGroups.cs
c:\Projects\MyProject>
I've tried this on two different machines on two separate clones and I'm seeing the same thing.
Any other thoughts for how I could diagnose or fix this?
Clearly something has changed but if it's not showing in hg diff --git how can I establish what that might be?
Update 2014/12/10:
I've done a bit more checking on the history of the two parent revisions and I think I see why it's getting confused.
We've got the original parent file added in revision 1 on default.
On the Apple branch the file has been renamed to move it to a new location.
On the Orange branch the file has been added to move it to the same new location.
So the file on both branches is binary identical and at the same location, but presumably Mercurial is flagging it as a difference to be merged because they arrived there by apparently different means.
So the question then becomes:
Is there any way to retrospectively repair the move being treated as an add and delete on a long committed changeset (a new commit would be fine, but I can't edit the history) , or do I just need to let it go through in the merge?
Is there any way to retrospectively repair the move being treated as an add and delete on a long committed changeset (a new commit would be fine, but I can't edit the history)
Well... sort of. Update to the most recent Orange commit in which the files had their old names (you can use hg bisect to find it if you're not sure exactly when it happened), do hg rename to the new names, commit, and then merge this into the current Orange head. Mercurial should be smart enough to register the files as properly renamed, and it won't cause conflicts (we know this because the more complex Apple/Orange merge didn't).
or do I just need to let it go through in the merge?
This is easier. Mercurial's merging algorithm is quite smart. It can deal with situations like this just fine.
Unless you have a third branch in which the files were never moved, the second option is unlikely to cause a problem. If you do have such a branch, you should be fine as long as you merge it into a descendant of the Apple rename (or merge from such a descendant). The major difficulty would be with merges to or from the Orange branch.
While using Mercurial if I want to change the current working copy with a specific revision I just do:
$> hg revert good_revision
$> hg commit -m "Now I'm in the good revision"
Then I can see that all my files are int the good_revision state and can start working on it.
So far on fossil I can do a revert but only on specific files, not the entire repository, and update or checkout don't seem to work as I would expect.
How can fossil revert my entire repository to a certain revision?
I'm not sure I quite follow but I think what you want is to be able to create a "multiple heads on one branch" sutuation in Fossil. If yes, then Fossil does support this, just it calls branch's heads "leaves", and this process is called "forking".
To do that, you
fossil update good_revision
and then
fossil commit --allow-fork
You may now spawn fossil ui, navigate to your branch and see it having two leaves.
You now may close the then-current leaf.
Note that, while supported, this does not appear to be a recommended practice. Instead, Fossil recommends a rather peculiar approach for throwing away changes:
Rename the branch at the "bad" leaf to "mistake" (or create that branch if it doesn't yet exist). By doing this you effectively "mark" the resulting subleaf as a mistake.
Note that the name "mistake" name is just a convention; this branch does not exist in a freshly created repository.
Close the "bad" leaf.
Return to the last-good state using fossil update, continue hacking.
Since that "last-good" commit still inherits the branch tag of its parent commit, the next commit you record will also inherit it and won't be on the branch "mistake".
For an example, see how it looks in the SQLite repo—there's a bunch of assorted short chains of commits on this branch. See also this.
My slightly different solution to what I think I understand the question to be (paraphrased: how to work on an older "good_revision" than current leaf of this branch/trunk that I'll call bad_leaf, and treat changes since "good_revision" as bad), which is sort of equivalent to applying diffs between the two versions but in reverse from/to order:
Merge in a (empty) fork from the good_revision, using the baseline from the bad_leaf instead of the default, last common commit; hence the diffs that will be applied are the original branch's differences back to a good_revision fork you create as it won't see they've already been applied. Using the latest as baseline "hides" those which would otherwise make it ignore all changes as they're already applied.
fossil update good_revision
fossil commit --allow-fork --allow-empty
# note the uuid from that commit (for use as forked_basis below)
fossil merge -f --integrate --baseline bad_leaf forked_basis
Then of course once happy,
fossil commit
It doesn't create any branches that should be called "mistake", it just applies the reverse diffs from good_revision to bad_leaf into bad_leaf to put you back where you were and you can continue committing to that same (new) leaf that used to be at bad_leaf.
A diff (straight gnu, not fossil diff) against a checkout at the original good_revision compared to a checkout after the above commands matched. Except for empty directories that had lost their files, but fossil doesn't track/tidy-up dead directories anyway.
caveat: I haven't been using fossil that long and its different in several ways to the common ways I've been used to with cvs/svn/git/hg/ perforce/clearcase.
Reason for adding this answer: I found the existing answers harder to understand and wasn't sure I trusted myself to do them correctly as a result.
If I understand your question correctly, there was a problem somewhere along the development cycle and you would now like to go back one or more revisions to a known good revision and start using that. Furthermore, you'd like that revision to become your trunk. The approach in Fossil is similar to that of Mercurial:
fossil revert -r good_revision
fossil commit -m "Now I'm in the good revision"
This will replace the files in the working directory with the ones from the specified revision. The commit will commit them to whatever branch you're working on (I am assuming that it is the trunk in this example). If you don't specify the revision number, it will use the last committed version.
One of the more common usages of the revert command is to roll back a single file:
fossil revert -r good_revision my_file
(or)
fossil revert my_file_from_the_last_commit
However, as shown in the first example, leaving out the file name causes all files to be reverted. For further information please see https://www.fossil-scm.org/index.html/help?cmd=revert
Sorry for the latest response, but I just came across the question while looking for something else. I post this in case someone else is looking into how to revert to a previously committed version stored in Fossil.
I have a project stored in mercurial which has grown well beyond its original remit, and now I want to split the repository into two separate projects. Say the file tree looks something like this:
src/
a/
a.h
a.c
b/
b.h
b.c
Say I've hg cloned this repository twice, and in the first clone I've performed an hg rm src/b/*, and in the second I've performed an hg rm src/a/*. This gives me the two separate source trees I want, with history and revision numbering preserved in each branch.
The problem I now have is what happens if, in the future, I ever accidentally pull from the a/ clone into the b/ clone. What I'd like is for mercurial to simply refuse to pull from, or push to, the other branch, if I ever try to do so, as if the two had never shared history.
Is this possible? If not, is there a canonical way to create two parallel projects from one original which preserves history and revision numbering?
The canonical way would be to use hg convert with a filemap like this:
exclude b
rename a .
(and afterwards with the roles of a and b reversed to create the second repository)
This way you end up with two unrelated repositories (which Mercurial will refuse to push/pull without the use of force) only containing the history of a single directory.
Also see this question for reference.
Say if I have a good revision: 3200. Then I want to test something, and since it has 10 lines of change, and I need to remove a few lines, even though I am still testing I commit first, and after some changes, commit again, and let's say, I did 6 commits.
Now I want to put this on hold, but I don't want to lose all the testing and code written, so I want to
$ hg up -r 3200
which is the good, stable revision I want, and now can I commit and push as the tip? (if possible I want to avoid backing out hg backout because it looks bad somewhat, and I don't want to rollback because rollback has side effect of "if someone pulled from me during this time, the change can somehow get back in the repo")
Putting things on hold can be done in several ways in Mercurial. The simplest way is to simply not push it anywhere. After you go back in history with
$ hg update 3200
you can use
$ hg push -r .
to push only up to revision 3200. The . is important — it means the working copy parent revision, which in this case is 3200. Revision 3200 wont be "tip" in your local repository since you still have revisions 3201–3206, and the highest numbered revision is always what we call "tip". In other words, the history looks like this:
[3199] -- [3200] -- [3201] ... [3205] -- [3206]
^ ^
"." "tip"
where I've marked the current working copy parent revision and the tip revision.
When you start working based on revision 3200, the graph will change into
[3199] -- [3200] -- [3201] ... [3205] -- [3206]
\
\-------------------------------- [3207]
^
".", "tip"
Please try not to add too much emphasis on "tip". It changes all the time and is generally not very interesting. If you jump back to 3206 and make a commit, then tip will denote the newly created revision 3208 in your repository. In another repository, tip can be something else, depending on what was pulled from you and when it was pulled.
If you often need to do hg push -r ., then I suggest you create an alias for it. Such an alias would be a gentler push and could therefore be called "nudge":
[alias]
nudge = push -r .
With that in your toolbox, you can always do
$ hg nudge
to send the changesets you've just created up to the server, without worrying about sending up any other branches that you might have put on hold.
Finally, remember that you can use
$ hg update 3206
$ hg commit --close-branch -m "Abandoning this line of development"
to mark the 3206 changeset as "closed". This means that it wont show up in hg heads and it wont be considered for merging when you run hg merge. You will need to use hg push --force if you push it to the server, but and is okay since you're not creating multiple open heads, you just add another closed head.
The trouble with multiple open heads is really that a new hg clone might update to one of them and that would be confusing — people wouldn't know where to start working. With recent versions of Mercurial, hg clone won't update to closed heads so you avoid this problem.
You can re-open a closed head by simply making a child commit based on it. This means that you can close a line of development temporarily with no ill effects, other than a note in the graph saying that the branch was closed at some point.
From the question and the accompanying comments, it sounds like you want all new changes to be based on 3200, leaving previous work based on 3200 as a separate branch. It's easy to do:
hg up 3200
# work work
hg ci -m "new work based on 3200"
but there isn't any way to mark 3200 as tip, as far as I can tell. Once you commit something based on 3200, that new changeset will be tip, so you could make some benign change and commit that to create the new tip, but that's kind of kludgy. Another option if you are concerned that fellow collaborators won't know to use 3200 as the basis for their work because mercurial won't have it marked as tip is to give it a tag and tell team members to make sure and update their working copy to that tag before beginning their work.
krupans answer is of course correct, and he already mentions the problem of having now two head. But I'd like to stress that you will then have two heads of the same branch, and it could be difficult for other people to understand what's going on, and which head to use.
For this reason, it might be beneficial to put your testing code into a new branch, and for that you'll have to rewrite the history. You can do this with the MQ extension (assuming 3201 is the child revision of of rev 3200, and 3206 is the last of your testing commits:
hg qimport -r 3201:3206
hg qpop -a
hg branch branchname
hg qpush -a
hg qfinish -r 3201:3206
Try this out on a clone of your repo!
This should only be done if you haven't already pushed these changes to some other places.
I understand that CVS is obsolete system in out time but my company use it.
Problem is the next. As usual when developing starts we create branch from head and start work. Some times later we re-base branch with head and merge head with branch. It is ok. But every next typically operations are with problem. Many-many files are marked as changed, but in fact files hasn't any changes! . And these files aren't become white they red. It's a problem, because we need to review all of it to be sure that file modified.
To re-base branch with head we have do (using WinCVS):
1.Click Update.. on some branch;
2.Check Create missing directories;
3.Check Get the clean copy;
4.Check Update using last check in time;
5.Select Revision to update;
6.Select Merge type.
Any ideas why this can happen?
Thanks.
Tag the HEAD after each rebase, and next time you rebase, set the root tag to the last tag you made.
Like this:
Create BRANCH from HEAD, tag HEAD with BRANCH_ROOT_1
Do some work in HEAD
Merge HEAD into BRANCH with root branch BRANCH_ROOT_1, tag HEAD with BRANCH_ROOT_2
Do some more work in HEAD
Merge HEAD into BRANCH with root branch BRANCH_ROOT_2, tag HEAD with BRANCH_ROOT_3
...
GIT and (recently) SVN do this sort of thing automatically, but with CVS you need to do it manually after each merge. It's one of many reasons CVS is to be avoided like the plague.
I would suggest checking line endings (Win/Unix).
I have seen problems with all files marked as changed because of time zone problems. For example files checked out on a server using UTC, and copied over the network to a pc using CET. Or a change in daylight savings time caused such problems.
I have always used TortoiseCVS and it's Merge command, so I don't know much about WinCVS.