Mercurial: Merge in accidentally created subfolder - mercurial

TLDR: I seem to have created a separate repository in a subfolder of my main project. How can I combine them?
I have a project folder, let's call it BOB. I cloned (hg clone) BOB to a new folder called BOB2. To add new features, I created a subfolder on BOB2 called BOB-newfeatures. I have been working on this BOB-newfeatures folder for a while, with many checkins.
Today I realized that somehow I created a separate repository for BOB-newfeatures (I hadn't changed anything on BOB2 main until today so I hadn't noticed that changes weren't being tracked). If I do hg status on BOB2, it doesn't know about changes in the subfolder and vice versa.
Is there a way to stitch these together? I know I could hg add all of the files in BOB-newfeatures to BOB but then I think I lose all of my checkin history.

OK, I reconstructed (I hope) your case, with your names, starting from
BOB2>hg log -T "{node|short}\tFiles: {join(files, ', ')}\n"
25a16a8fea5e Files: Sub/3.txt
bf3c6cacb4a4 Files: 1.txt, 2.txt
ff71a2b1bbe3 Files: 1.txt
and nested repo
BOB2\BOB-newfeatures>hg log -T "{node|short}\tFiles: {join(files, ', ')}\n"
acac7d413ed2 Files: f1.txt
15a1f9cacf25 Files: f2.txt
f3055921fa01 Files: f1.txt
As a additional confirmation of invisibility of BOB-newfeatures inside BOB2
BOB2>hg manifest
1.txt
2.txt
Sub/3.txt
Method of solving problem - using Convert extension with --filemap in inversed, compared to Wiki, direction: it's example transform subdir of repo into separate repository, I'll move repository-root into subfolder
map-file, prepared for conversion
rename . BOB-newfeatures
conversion
hg convert --filemap map z:\BOB2\BOB-newfeatures z:\BOB-newfeatures-conv
initializing destination z:\BOB-newfeatures-conv repository
scanning source...
sorting...
converting...
2 New feature started
1 Change 1
0 Change 2
Testing results
BOB-newfeatures-conv>hg log -T "{node|short}\tFiles: {join(files, ', ')}\n"
a3b2c462a3b9 Files: BOB-newfeatures/f1.txt
f5f1168cfe2f Files: BOB-newfeatures/f2.txt
da27a50a5cb6 Files: BOB-newfeatures/f1.txt
compare file-paths with log from nested repo, note different hashes for changesets
Next bad news: you can't just pull from BOB|BOB2 into converted repository missing parts easy
BOB-newfeatures-conv>hg pull ../BOB2
pulling from ../BOB2
searching for changes
abort: repository is unrelated
Even with --force (because repositories are really unrelated and doesn't share history) you'll get "dirty" combined repository (changes in root and in BOB-newfeatures/ are two separate lines of changes with own roots and tips)
BOB-newfeatures-conv>hg pull ../BOB2 -f
pulling from ../BOB2
searching for changes
warning: repository is unrelated
requesting all changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 4 changes to 3 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
And at last step you have to re-link two histories into one common. In my case due to my actions (pulling to converted repository with pre-existing history of BOB-newfeatures) I had to link 0-1-2 revisions after 3-4-5 (historically earlier changes) and I don't know more elegant way to do it, than again convert (HG->HG) repository, with --splicemap this time
With log output
>hg log -T "{rev} {node}\n"
5 25a16a8fea5e5b4dac42a0a6b2c8e82890c220a3
4 bf3c6cacb4a4c22cb5720ddeab1ec5f8238a98c9
3 ff71a2b1bbe30a56c9dabc9a7ddb2bbccad840af
2 a3b2c462a3b917b3ba58daee3df2632875baee17
1 f5f1168cfe2f4b6c67d0af8a9259665ae2d40bd5
0 da27a50a5cb6246c03c6af7485ac7ffc33e62738
splicemap for rule "0 after 5" can be created (with format of oneliner "ChildHash ParentHash")
da27a50a5cb6246c03c6af7485ac7ffc33e62738 25a16a8fea5e5b4dac42a0a6b2c8e82890c220a3
and last conversion performed
>hg convert --splicemap z:\map z:\BOB-newfeatures-conv z:\BOB3
scanning source...
sorting...
converting...
5 Initial data
4 Changes
3 More changes
2 New feature started
spliced in 25a16a8fea5e5b4dac42a0a6b2c8e82890c220a3 as parents of da27a50a5cb6246c03c6af7485ac7ffc33e62738
1 Change 1
0 Change 2
with expected good results

You simply created a separate repository. As such you can pull from that repository like from any other. In this case, in your main repository in BOB2, you could do:
hg pull ./BOB-newfeatures
In order to avoid confusion, I'd first move BOB-newfeatures to the same directory level as BOB2 and pull then giving the new relative path ../BOB-newfeatures; but that's more for cosmetics and to keep your BOB2 repository clean; strictly speaking it should not be needed.
(Basically you used a feature of hg: you can create a new repo in any sub-path which will be an independent repo which knows nothing of the parent and vice versa. It's used for instance for libraries needed by the main repo but which you do not want to tie directly to your main; they then are found in the expected relative path and it's easy to operate on)

Related

Mercurial - Pull changes after Clone

Say I cloned a remote repository and called it "A"
Then I cloned another remote repository and called it "B"
"B" has the .hg folder and src folder , and "A" only has the .hg folder.
If I pull changes from "B" to "A", should now "A" also contain the src folder? Because that's exactly what I did and it did not
You mix the concepts of 'repository' with the working directory, the actually checked-out changeset, which indicates the state of the repository at a particular revision.
If the two repositories A and B are pulled into one repository, all changesets are present there, but they are present in different changesets. If you want to bring them together, you have to merge two changesets; most likely you want to merge the two heads you have, the one from repository A and the one from repository B. For example:
# check heads:
hg heads --template="{rev}:{node|short} {desc}\n"
2332:d69c8aaf6db6 Doc: Changelog as it should have been
2128:6f38df710194 Added tag 0.2.5 for changeset 6d89bb9ad3f6
Update to one head and then merge the other. Make sure to use the actual revisions:
hg up -r2332
hg merge -r2128
Whether or not that works without any conflicts depends on how A and B look like.
Does src contain any files? You cannot add an empty directory to a mercurial repo. If you tried hg add src and src was empty, you won't get an error but nothing happens. If that's really what you want, there are ways, but it sounds like you're just experimenting.
More specifically: You can only add files, and the directories that contain them are added implicitly. After you create a file in src, add the file to the repo and commit the change (along with anything else you may want to bring along). Now you have a changeset you can push or pull to repository "B".
Once the changeset has become part of "B"'s history (check with hg log), you need to update to it (hg update); or, if you've ended up with a branch, merge it to your current branch.

Mercurial move followed by diff

I had two very large projects in my Mercurial repository.
I am in the process of refactoring both of them into smaller sub-projects.
That involves moving sets of sources from a parent project directory into a sub-project's sub-directory.
For most files, I simply moved them.
For some files, I also had to make changes.
Before I commit my refactoring changes, I would like to review any edits that I made to any source files. In the GUI tool SourceTree - it shows me any modifications (in addition to indicating that the file has been moved/renamed). Is there any way to determine what files have also been modified from the Mercurial command line?
Here is a specific example of what I am talking about:
iphonedev:EveryScape cdoucette$ hg status -C Engineering/iOS/ESSDK/src/ESSDK-Miscellaneous/ESDataManagerInMemory.m
A Engineering/iOS/ESSDK/src/ESSDK-Miscellaneous/ESDataManagerInMemory.m
Engineering/iOS/ESSDK/src/ESDataManagerInMemory.m
How can I compare the old revision with the current working copy in a different location?
If I just do this:
hg diff Engineering/iOS/ESSDK/src/ESSDK-Miscellaneous/ESDataManagerInMemory.m
It shows me the entire contents of the file (since technically it was added in its new location).
Instead, I want to diff between:
Engineering/iOS/ESSDK/src/ESDataManagerInMemory.m (repository copy - previous revision)
Engineering/iOS/ESSDK/src/ESSDK-Miscellaneous/ESDataManagerInMemory.m (working copy)
I did search for similar questions. This post was close - but appears to only make sense if I went ahead and committed my changes. Instead, I would like to find and review my changes before committing.
Mercurial diff not working after move/rename
I would script it up like this:
hg cat -r <oldrev> <oldfilename> > oldfile.oldrev
diff <newfilename> oldfile.oldrev

how to ignore files in kiln/mercurial using tortoise hg "that are part of the repository"

We use tortoise hg with Kiln. In my vs 2010 c# project there are some files that are part of the repository but I would like tortoise hg to ignore them when I make a commit.
For eg., say in a login screen I may hard code the userid, password for testing. I dont really want this file considered during a commit. I understand .hgignore file but this really works for files that are not part of the repo. Any trick in tortoise hg to ignore files that are part of the repo ? (so they do not show up as modified (M) during a commit.) thanks
I always use a combination of .hgignore and BeforeBuild (in the .csproj file) for things like this.
In one of my pet projects, I have the following setup:
App.config contains my real hardcoded user id and password for testing.
App.config.example is identical, but with fake data like "dummy_user" and "dummy_pw".
App.config is not part of the repository, and it's ignored (in .hgignore).
App.config.example is part of the repository.
Then, I have the following in the BeforeBuild target in the .csproj file of my solution:
<Target Name="BeforeBuild">
<Copy
Condition="!Exists('App.config')"
SourceFiles="App.config.example"
DestinationFiles="App.config"/>
</Target>
All this together has the following effect:
the config file with the real data can never be accidentally committed to the repository, because it's ignored
the repository only contains the config file with the example data
if someone else clones the repository to his machine, he won't have the "real" config file...but if it's missing, it will be automatically created before the first build by Visual Studio / MSBuild by simply copying the .example file (and then he can just put his real login data into the newly created App.config file).
if an App.config with real hardcoded user data already exists, it won't be overwritten when building because the BeforeBuild event will only happen if App.config does not already exist
The answer by Christian is the right one, but I want to mention that TortoiseHg supports what you want with their Auto Exclude List.
One problem with an exclude list is that it cannot work with merges: you must commit all files when you merge and so you'll have to do a little dance with shelve, merge, commit, and unshelve.
When you do a TortoiseHG commit, there is a list of files with checkboxes by them. Deselect the files you do not want comitted.
Or, on the command line, do a commit of the form hg commit --exclude "pattern", where pattern is defined in the hg man page.
You could always use hg forget.

Mercurial: Multiple Change sets at once?

Before, when I was using perforce, I could work on multiple bugs at once as long as the code did not affect the same files, by having multiple change sets open at once.
Changeset 1:
A.txt
B.txt
C.txt
Changeset 2:
D.txt
E.txt
F.txt
I could submit changeset 2 to the repository without submitting changeset 1 (because it's still in progress)
Is this possible with Mercurial? other than doing each file as a separate commit?
You can always just do: hg commit D.txt E.txt F.txt to commit just those files which will leave A.txt, B.txt, and C.txt uncommited. Using the -I option to commit lets you do those with patterns if they're, for example, in a common directory: hg commit -I 'dir1/**'
You can have two separate branches (working copies) and make one change in and the other in the other. That's one way.
Another is to use Mercurial Queues. You can use qpush --move to change the order of changesets if they have no dependencies on one another, so you can then use qfinish to 'commit' the first changeset that's ready.
You don't actually hold changesets "open" in Mercurial.
Either you've committed your changes, or you haven't.
You can, however, have multiple files with uncommitted changes, and only commit a few of them. It is even possible to commit parts of files, chunks, instead of the whole file.
If I was to do what you're asking I would simply make another clone locally from my first one, and work on the two different fixes in two different working folders. Then I have all the freedom I need to combine the two (push/pull locally), push to the server, etc.
In Mercurial, cloning is a cheap operation when done locally. Just clone the repository for each thing you are working on. Push back to the main repository as each thing is ready:
hg clone http://project project
hg clone project project-bugfix // uses hardlinks and is inexpensive.
hg clone project project-feature
<edit bugfix and feature as needed>
But remember that the default push location is the project cloned from, so you'll either need to edit .hg\hgrc's default push path for the "project" clones, or make sure to hg push http://project from "project-bugfix" and "project-feature" when complete.
Even if your modifications touches the same file you can select what to include (hunk by hunk). You just have to activate the record extension (it's installed by not activated by default).
To activate the record extension, put this in the [extensions] section of your .hgrc:
[extensions]
hgext.record=
Then to commit, replace hg commit by hg record. Let's assume your example change sets with a G.txt file that have changes for both change sets. Commit with:
hg record D.txt E.txt F.txt G.txt
Answer questions, for example:
2 hunks, 6 lines changed
examine changes to 'D.txt'? [Ynsfdaq?] f # f for full file (help with ?)
... skipped file E and F
6 hunks, 35 lines changed
examine changes to 'G.txt'? [Ynsfdaq?] y
## ... (patch hunk here)
record change 6/16 to 'G.txt'? [Ynsfdaq?] y # y to include the hunk, n to skip

Mercurial - How do I create a .zip of files changed between two revisions?

I have a personal Mercurial repository tracking some changes I am working on. I'd like to share these changes with a collaborator, however they don't have/can't get Mercurial, so I need to send the entire file set and the collaborator will merge on their end. I am looking for a way to extract the "tip" version of the subset of files that were modified between two revision numbers. Is there a way to easily do this in Mercurial?
Adding a bounty - This is still a pain for us. We often work with internal "customers" who take our source code releases as a .zip, and testing a small fix is easier to distribute as a .zip overlay than as a patch (since we often don't know the state of their files).
The best case scenario is to put the proper pressure on these folks to get Mercurial, but barring that, a patch is probably better than a zipped set of files, since the patch will track deletes and renames. If you still want a zip file, I've written a short script that makes a zip file:
import os, subprocess, sys
from zipfile import ZipFile, ZIP_DEFLATED
def main(revfrom, revto, destination, *args):
root, err = getoutput("hg root")
if "no Merurial repository" in err:
print "This script must be run from within an Hg repository"
return
root = root.strip()
filelist, _ = getoutput("hg status --rev %s:%s" % (revfrom, revto))
paths = []
for line in filelist.split('\n'):
try:
(status, path) = line.split(' ', 1)
except ValueError:
continue
if status != 'D':
paths.append(path)
if len(paths) < 1:
print "No changed files could be found."
return
z = ZipFile(destination, "w", ZIP_DEFLATED)
os.chdir(root)
for path in paths:
z.write(path)
z.close()
print "Done."
def getoutput(cmd):
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return p.communicate()
if __name__ == '__main__':
main(*sys.argv[1:])
The usage would be nameofscript.py fromrevision torevision destination. E.g., nameofscript.py 45 51 c:\updates.zip
Sorry about the poor command line interface, but hey the script only took 25 minutes to write.
Note: this should be run from a working directory within a repository.
Well. hg export $base:tip > patch.diff will produce a standard patch file, readable by most tools around.
In particular, the GNU patch command can apply the whole patch against the previous files. Isn't it enough? I dont see why you would need the set of files: to me, applying a patch seems easier than extracting files from a zip and copying them to the right place. Plus, if your collaborator has local changes, you will overwrite them. You're not using a Version Control tool to bluntly force the other person to merge manually the changes, right? Let patch deal with that, honestly :)
In UNIX this can be done with:
hg status --rev 1 --rev 2 -m -a -n | xargs zip changes.zip
I also contributed an extension, see the hgexportfiles extension on bitbucket for more info. The export files extension works on a given revision or revision range and creates the set of changed files in a specified directory. It's easy to zip the directory as part of a script.
To my knowledge, there's not a handy tool for this (though a mercurial plugin might be doable). You can export a patch for the fileset, using hg export from:to (where from and to identify revisions.) If you really need the entire files as seen on tip, you could probably hack something together based on the output of hg diff --stat -r from:to , which outputs a list of files with annotations about how many lines were changed, like:
...
src/test/scala/RegressionTest.scala | 25 +++++++++++++----------
src/test/scala/SLDTest.scala | 2 +-
15 files changed, 111 insertions(+), 143 deletions(-)
If none of your files have spaces or special characters in their names, you could use something like:
hg diff -r156:159 --stat | head - --lines=-1 | sed 's!|.*$!!' | xargs zip ../diffed.zip
I'll leave dealing with special characters as an exercise for the reader ;)
Here is a small and ugly bash script that will do the job, at least if you work in an Linux environment. This has absolutely no checks what so ever and will most likely break when you have moved a file but it is a start.
Command:
zipChanges.sh REVISION REPOSITORY DESTINATION
zipChanges.sh 3 /home/hg/repo /home/hg/files.tgz
Code:
#!/bin/sh
REV=$1
SRC_REPO=$2
DST_ZIP=$3
cd $SRC_REPO
FILES=$(hg status --rev $1 $SRC_REPO | cut -c3-)
IFS=$'\n'
FILENAMES=""
for line in ${FILES}
do
FILENAMES=$FILENAMES" \""$SRC_REPO"/"$line"\""
done
CMD="tar czf \"$DST_ZIP\" $FILENAMES"
eval $CMD
I know you already have a few answers to this one but a friend of mine had a similar issue and I created a simple program in VB.Net to do this for him perhaps it could help for you too, the prog and a copy of the source is at the bottom of the article linked below.
http://www.simianenterprises.co.uk/blog/mercurial-export-changed-files-80.html
Although this does not let you pick an end revision at the moment, it would be very easy to add that in using the source, however you would have to update to the target revision manually before extracting the files.
If needed you could even mod it to create the zip instead of a folder of files (which is also nice and easy to manually zip)
hope this helps either you or anyone else who wants this functionality.
i just contributed an extension here https://sites.google.com/site/alessandronegrin/pack-mercurial-extension
I ran into this problem recently. My solution:
hg update null
hg debugsetparents (starting revision)
hg update (ending revision)
This will have the effect of deleting all tracked files that were not changed between those two revisions. You will have to remove any untracked files yourself, though. After doing this, the local branch will be in an inconsistent state; you can fix this by running hg debugrebuildstate (or simply deleting the local branch, if you no longer need it).