I copied a large amount of data from my labs file server to my laptop, then accidentally committed it to the Mercurial repository I'm using to back up my thesis.
Now I have 200+ MB of data I don't need taking up space on my hard disk, even after I've deleted the files. This isn't really a problem, but the bitbucket repository I sync to only gives me 1 GB of space, which I will need for my data.
Stupidly I then deleted the files and committed again, so I can't just use rollback as described in https://stackoverflow.com/a/3290523/961959 without creating a new repository and having to reset up everything with bitbucket.
Is there a way I can fix this, so I don't waste a quarter of my repository space? Can I rollback the last 2 commits I did?
You can:
Use hg strip to remove the changeset where you've added the files and all of its
descendants (note that this will obliterate them completely, so only do it if these files are the only thing committed during this time).
Import those changesets to MQ and edit them.
Use hg convert from Mercurial to Mercurial with --filemap option.
Clone your repository up to faulty changeset and push from this one instead, as described in FAQ.
I'm going to describe what I would do if I wanted to roll back two most recent commits.
I assume that you haven't pushed to Bitbucked yet. I also assume you have these changesets on top of your DAG:
o C: Deleted files FILE1 and FILE2
|
o B: Some nice changes; also added large files FILE1 and FILE2
|
o A: Some good changeset
Here, C should be removed altogether, B should be edited (FILE1 and FILE2 additions should be rolled back), and A and below should be left as they are.
Caveat: this only works if B and C were not pushed onto Bitbucked (or any other public repo) yet.
You'll need to enable the MQ extension to do this. To do this, add these lines to the .hg/hgrc file in your repo:
[extensions]
mq=
Steps
First, I strip C:
$ hg strip C
Now, C is obliterated, and the parent is B. I import B as a Mercurial Queues patch to edit it:
$ hg qimport -r B -n B.patch
Now I have one patch on top our queue, which was created from B. I remove the big files, and refresh the patch:
$ hg forget FILE1 FILE2
$ hg qrefresh
Now B.patch no longer includes the big files. However, they are still on the disk, albeit not controlled bu Mercurial. I now finish my work with MQ:
$ hg qfinish -a
Here's what I have at the moment:
o B1: Some nice changes, no big files here
|
o A: Some good changeset
In case the changes are already pushed to BitBucket, it does offer an option to strip changesets from the server. After performing the strip locally, you should access the url:
https://bitbucket.org/<user>/<repo>/admin/strip
It'll offer an option to strip all changes following a specific commit.
NOTE: There used to be a link to reach that URL in the repo config menu. Now the only way to access it seems to be typing it directly.
Related
I'm looking for the simplest way strip all local commits (i.e. not committed in the remote repo) and remove all local bookmarks from a mercurial repository. I know I can run something like hg bo | xargs hg strip && hg bo | xargs hg bo -d (obviously with stripping out the commit hashes) but I've had trouble trying things like this when I have stacked commits.
Is there an easy (if a little heavy handed, maybe) way to blow away all local changes to your copy of the repository, leaving you with one that mirrors the remote repository exactly? Thanks!
In order to strip subtree, you can strip only oldest ancestor by hand
The strip command removes the specified changesets and all their descendants.
In order to get roots of not-published changesets, you can use revsets and templating. If you have single remote repo (with default alias) it will be just
hg log -r "roots(outgoing())" -T "{node|short}\n"
for many remotes revset can be modified to
roots(outgoing(PATH1) & outgoing(PATH2) ... & outgoing(PATHN))
or (with some assumtions: a) Mercurial have support for phases b) secret phase not used c) remote repo is ordinary "publishing repo")
roots(draft())
(not pushed changesets are in draft phase by default)
We have a master repository located on a separate server. I originally cloned the default branch and made my changes locally. I have locally commited those changes. However, there has been a branch created on the master repository that I would like to push my changes to. Below is the description of my attempt at getting this accomplished.
I have cloned the branch. I am trying to export my changes from local default like so:
C:\hg\default>hg export -g -o mypatch -r tip
and when trying to import them into the clone of the new branch, I get the following:
C:\hg\newBranch>hg import C:\hg\default\mypatch
applying C:\hg\Fill1\mypatch
patching file .hgignore
Hunk #1 FAILED at 11
1 out of 1 hunks FAILED -- saving rejects to file .hgignore.rej
abort: patch failed to apply
I can manually fix the .hgingore.rej file just fine. The problem is that the patch also contains files that were moved. Instead of the files showing as moved, I get the following when running hg status:
C:\hg\newBranch>hg status -C
M someOtherFilesThatLookAsExpected.txt
! originalLocaion\fileA.txt
? newLocation\fileA.txt
This missing and new status is for all files that were moved in the commit contained the applied patch. Am I doing something wrong? Do I always have to manually move files when applying a patch? Is there an easier way to accomplish this branch transfer?
That's a bit difficult to answer without knowing more about your repository structure, but here's how I'd go about it without knowing more. I'm assuming that the reason for the conflict is that there are conflicting changes in the same branch of the repository.
First, get the contents of the newBranch repository:
cd c:\hg\default
hg pull c:\hg\newBranch
Then, either merge or rebase your changes on top. If you are working on the same branch, then just using
hg pull --rebase c:\hg\newBranch
in lieu of the regular pull should do (assuming you have rebasing enabled). Otherwise, do an explicit merge or rebase of the two heads that you need to reconcile. Finally, do:
hg push -r tip c:\hg\newBranch
in order to get your (now reconciled) changes back into newBranch.
Unless you have very specific and unusual requirements, push and pull should be your normal way to sync repositories or part of them (note that using -r will only push/pull the respective branch). Export/import are rather low-level mechanisms that may not give you the benefits of the standard machinery that handles renames, three-way merging logic, etc.
Mercurial Queues is about patches, and patches know nothing about file renames. Is this the reason why Mercurial Queues don't support file renames, or am I doing something wrong renaming the file? I have worked on a patch queue modifying just one file called foo. Now I go back to patch 4 and rename the file via hg mv:
hg qpop 4 # Unapply all patches until patch 4.
hg mv foo bar # Rename file and led Mercuial know about it.
hg qrefresh # Should apply changes to unapplied patch 4.
hg qpush -a # Should apply all unapplied patches.
I get the following error:
unable to find 'foo' for patching
1 out of 1 hunks FAILED -- saving rejects to file foo.rej
patch failed, unable to continue (try -v)
patch failed, rejects left in working dir
errors during apply, please fix and refresh 5.diff
So how should I do to handle file renames with Mercurial Queues? Mercurial commits handle file renames for a reason (as without, it would lose the whole history about the editing of the file after renaming).
Update
Just noticed that hg histedit folding changesets and hg collapse also lose the information of file renaming, the file shows up as a new one instead of a renamed one, and I guess this is for the same reason. Seems like collapsing private changesets is not possible in Mercurial without loosing that information?
Update 2
Found out collapsing private changesets without loosing rename information is possible with hg rebase and its --collapse option, e.g. hg rebase -s 5 -d 4 --collapse. The issue that the other commands should sostain rename information is still vacant, but using the hg rebase command there is at least a way to achieve the desired result.
Is this the reason why Mercurial Queues don't support file renames,
no.
or am I doing something wrong renaming the file?
no.
Yes, patches in chain will have troubles, if they was prepared for foo file, but later in will be bar, but due to different reasons: patches are independent, and every and each patch know nothing about changes in others - they work with context, not with sequence of operations in separate patches. You done rename correctly, but this changeset invalidates later changesets, prepared on old content
I copied a large amount of data from my labs file server to my laptop, then accidentally committed it to the Mercurial repository I'm using to back up my thesis.
Now I have 200+ MB of data I don't need taking up space on my hard disk, even after I've deleted the files. This isn't really a problem, but the bitbucket repository I sync to only gives me 1 GB of space, which I will need for my data.
Stupidly I then deleted the files and committed again, so I can't just use rollback as described in https://stackoverflow.com/a/3290523/961959 without creating a new repository and having to reset up everything with bitbucket.
Is there a way I can fix this, so I don't waste a quarter of my repository space? Can I rollback the last 2 commits I did?
You can:
Use hg strip to remove the changeset where you've added the files and all of its
descendants (note that this will obliterate them completely, so only do it if these files are the only thing committed during this time).
Import those changesets to MQ and edit them.
Use hg convert from Mercurial to Mercurial with --filemap option.
Clone your repository up to faulty changeset and push from this one instead, as described in FAQ.
I'm going to describe what I would do if I wanted to roll back two most recent commits.
I assume that you haven't pushed to Bitbucked yet. I also assume you have these changesets on top of your DAG:
o C: Deleted files FILE1 and FILE2
|
o B: Some nice changes; also added large files FILE1 and FILE2
|
o A: Some good changeset
Here, C should be removed altogether, B should be edited (FILE1 and FILE2 additions should be rolled back), and A and below should be left as they are.
Caveat: this only works if B and C were not pushed onto Bitbucked (or any other public repo) yet.
You'll need to enable the MQ extension to do this. To do this, add these lines to the .hg/hgrc file in your repo:
[extensions]
mq=
Steps
First, I strip C:
$ hg strip C
Now, C is obliterated, and the parent is B. I import B as a Mercurial Queues patch to edit it:
$ hg qimport -r B -n B.patch
Now I have one patch on top our queue, which was created from B. I remove the big files, and refresh the patch:
$ hg forget FILE1 FILE2
$ hg qrefresh
Now B.patch no longer includes the big files. However, they are still on the disk, albeit not controlled bu Mercurial. I now finish my work with MQ:
$ hg qfinish -a
Here's what I have at the moment:
o B1: Some nice changes, no big files here
|
o A: Some good changeset
In case the changes are already pushed to BitBucket, it does offer an option to strip changesets from the server. After performing the strip locally, you should access the url:
https://bitbucket.org/<user>/<repo>/admin/strip
It'll offer an option to strip all changes following a specific commit.
NOTE: There used to be a link to reach that URL in the repo config menu. Now the only way to access it seems to be typing it directly.
Yesterday I committed a file and then wanted to hg backout, but Mercurial says cannot backout because I have other modified files in the project…
That's a little bit strange… it is not atomic level on each file? Commit 1 file and then backout 1 file?
Second, I can save a copy of those modified files A, B, C, to tmp files, hg revert them, and then backout, and then copy those tmp files back to A, B, C, and isn't that the same as just hg backout that last commit but just more work?
In general, doing a backout implies doing a merge. When merging, the working copy is used as a scratch space: merge conflicts show up as changes to the files in your working coyp, and you resolve them by editing the files in your working copy. This is the reason why Mercurial insists on you having a clean working copy before you merge or backout: there is really no other good place for Mercurial to store the files when it needs you to resolve conflicts.
Personally, I've never run into this problem. I never have modified files lying around -- I either commit them or I stash them in a MQ patch. If you don't want to use MQ, then a simple
hg diff > tmp
hg revert --all
# working directory is now clean, do your merge/backout/...
hg import --no-commit tmp
is enough to deal with your case. This has of course been wrapped into easier commands by the nice people who write extensions: see the attic extension for an example.
Nope. Mercurial is not a file-revision tool, it's changeset-revision. A changeset includes all the files affected by particular change, not individual files.
Yes, theoretically doing revert on all open files, backout and then editing those files again will achieve the same effect as doing a backout of the individual file. However, in practice the history for the repo does not contain separate entries for each file, so you can't roll back only one of the files.