How does Mercurial handle splitted files? - mercurial

How does mercurial handle splitted files? What will happen if I create a branch and split a file. Can I easily pull changes from another branch which modifies the original, unsplitted file?

I just did a little experiment. I created one repository (foo) with one big file. Then I cloned that into bar, used hg cp to copy the file into two files, and removed one half in both files. Then I made a change affecting the whole file in foo, and merged that into bar.
As a result, the parts contained by the respective split file were merged correctly, while I got a conflict for the removed parts: my local version was empty, while the other version was the change from foo.
So if you're happy with removing these kinds of conflicts every time you merge, this might be good enough for you.

After reading the clarification comment, the answer is no. Mercurial tracks files, not hunks of code, so it can't do that as far as I know.

Related

Mercurial: How do I fix an incorrectly published rename/copy?

I've somehow marked a bunch of files as being "copy/renamed" instead of just marking them as new files.
I've also published these changes to our central repository and can cannot strip them out (we've already got some changes on top and I don't have the permissions/ability to fiddle with the central repository anyway).
Context:
I've actually done it to a whole bunch of files, but here's an example of what I did to one: I've copied a file called "Labels.properties", to a new file called "Labels_ja.properties" (the new file contains a subset of the original properties, and eventually all the values will be translated to a different language). The "Labels_ja.properties" file has been marked as a copy/rename of "Labels.properties" (the only way I've been able to see exactly what's happened is by looking with SourceTree, which shows "File copied/renamed from Labels.properties").
Our environment is a sort of central repository with automated "pull request" style merging tools built on top, so solutions involving all our developers magically knowing exactly how to drive Hg in order to resolve these conflicts aren't going to work - it's the scripts that are getting the merge conflicts.
These copy/renames are causing a lot of hassles: when people touch the original versions of the property files (they don't even know about the copied files yet) - it looks like Hg is trying to merge those changes onto the copies, but because the files are very different, those merges are failing with conflicts.
Problem:
What can I do to sort out all these merge conflicts that our automated merge scripts are getting?
Ideally, I'd like to go back in time and just mark all these files "new" - but there's no going back now that the changesets have been published.
Can I just make a big backout commit, then re-add the files (making sure that they are marked "new" and not "copy/renamed")?
I cannot think of a good solution. Even if you delete the files, Mercurial will still complain repeatedly when they get changed and merged. The simplest solution I can think of is moving the bad files into some "attic" directory where they don't hurt anyone and never touching them again. Then add the real files where they belong.
If I understand correctly, the problem is in fact that the developers are still based on a revision that does not have your move.
When they change the original file, an 'hg merge' will then smash together the changes from the developer and the changes to the new file in that new file.
I see a few solutions for this:
You can tell the developers to rebase their changes on top of the new changes. This will actually not work, since rebase will make the same mistake as merge.
The developers can turn their changes into patches and apply their patches on top of your changes. Their patches will refer to the original files, not the changed files, so this should work fine for the tools that merge later on.
The above flow can be done in a more sophisticated way using Mercurial Queues: import the existing developer commits as patches, then qpop all of these, update to your newer revision and qpush all of the revisions again.
Mark the head with your changes as 'closed' using '--close-branch'. However, if your tools are not equipped to handle this correctly (by ignoring the closed branch), this may cause issues. Branches are reopened when a new commit is done on top of the branch. So if you merge developer changes with the closed branch, it will open again.

How to see all changes to a specific file across all branches?

The project I'm working on using a lot of branches. I know there's been some changes to a particular file that I need on another branch, but I don't know what branch they were done on.
How can I find all changes done to a specific file, searching across all [named] branches?
I'm not sure if I'm misunderstanding the question, but hg log <filename> shows all changesets that include changes to a file, no matter what (named or unnamed) branch they're on.

mercurial temporarily ignore versioned files

My question is essentially the same as here but applies to mercurial. I have a set of files that are under version control, and one save operation changes quite a lot of files. Some of the resulting changes are important for revision control, and some of the changes are just junk. I can "partition" off the junk into separate files. These junk files need to be part of a basic checkout in order for it to work, but their contents (and changes over time) aren't that important for revision control. Right now I just tell all our developers not to commit these files, but we all forget and it creates a lot of extra baggage in the repository. I don't really like the svn solution proposed because there are quite a lot of files and I want a simple clone to just work without all this extra manual work, so I was wondering if mercurial has a better alternative. It's kind of like hg shelve but not quite, and kind of like ignore, but not quite. Is there some hg extension that allows for this? Can git do it?
Mercurial doesn't support this. The correct way to do it is to commit thefile.sample and then have your developers (or better you deploy script) do a copy from thefile.sample to thefile if thefile doesn't exist. That way anyone can update the example file, but there's no risk of them committing their local changes (say their personal database connect string).
Aha! So TortoiseHG's repository and global settings have an Auto Exclude List where you can define a list of files that will be unchecked by default when the status, commit, and shelve dialogs open. So they still show up, but the user has to check them in order to actually do a commit. The setting is stored in hgrc, but it's under the [tortoisehg] heading so it's not supported by mercurial per se. Nevertheless, it fits my needs.
One solution to this is to use nested tree support (submodule in git), where the "junk" would be put in a different repository (to avoid cluttering the main repo), while enabling checking out the whole thing out in a consistent manner (right version of both repos in sync).
https://www.mercurial-scm.org/wiki/Subrepository?action=show&redirect=subrepos
In git, submodules are one solution to this issue - but they are not that great UI-wise. What I do instead is to keep two completely independent repositories, and using the subtree merge strategy when I need to update the main repo with the junk repo: http://progit.org/book/ch6-7.html

With Mercurial, is it possible to have default branch in one shell, and another branch, "bugfix", in another shell?

Because it seems like when
hg up default
or
hg up bugfix
is used in one Bash shell, then the other shell also changes to that branch automatically if an hg branch is used to show which branch it is. (so I think if it is a
Ruby on Rails server running, all of a sudden, the code will change to the other branch)
If using two separate clones, it can be done... as if there are two branches... but can be done using the branch feature of hg?
You have to use two separate clones.
Think about it. You're working on two different versions of a file. They differ in content. You have to change the file to reflect one of the two branches. How can a single file have two different contents at the same time (your two-shell idea)?
A different analogy: a shell is a window. The file is an object in the room. Even if you have two windows looking into the same room, you can't have the one object in the room be two different things at the same time. To do that, make an identical room next door, modify the object, and have the second window attached to the cloned room.
The different shells seem to be working on the same repository directory. This won't work since the directory is where the update happens and not the shell.
So you really need two repository directories i.e. clones in order to do this.
If these directories are on the same filesystem this won't cost much time or space since Mercurial optimizes this case by using hard links.
At least if you are on a operating system supporting hard links.
If by "shell" you mean two command shells open to the same directory, then yes, they both change because they are working with the same working directory.
One working directory can only ever be at one place in the repository history.
To work with two different branches or changesets in the project at the same time, make a second clone from the first, and then you can manipulate each independently.

mercurial: "Cloning" just one file from one repository into another one?

I've got a perl project's mercurial/hg repository here with a lot of modules. Now, I've realized that some of the modules, a branch of modules, does not fit into this project anymore but would be better suited in another project.
So, is it possible to "clone" these modules from repository1 into my other repository2 while keeping these modules's revision history and at the same time flagging the modules in repository1 as "removed"?
I think it is possible with a number of steps. But I think cloning the whole repo1 and then removing all the unnecessary files would clutter my new repo2 with a lot of unrelated revision history. Still, as I understand the "clone" and "pull" commands neither of them is suited to clone just a slice of another repository, right?
Or is it possible to "move" a file from one repository into another? As I see it that's the analogy of what I want to do..
Absolutely! Take a look at the Convert extension, specifically the Mercurial-to-Mercurial section which should do exactly what you want.
After you've split off those modules, you can use hg forget, hg remove to remove them from your original repository, or even use hg convert again to create a new repository without them.