Mercurial: Better command line diff? - mercurial

I am wondering how to improve the diff command as part of hg. For example, lets say I have this code:
line 1
line 2
lin3 3
and I change it to become:
if($condition) {
line 1
line 2
line 3
}
hg diff will show the original three lines with a "-" and the new five lines with a "+". Even when I run with -wbB to ignore whitespace and line changes. I understand what it is trying to tell me, but isn't there way it could be "smarter" and realize that I've only added two lines (and increased level of three lines)?
EDIT:
Is it possible to have hg diff tell you what text was added and where? As opposed to how the "structure" of the code changed because of those additions?
EDIT 2:
I am running Debian (Linux dev 2.6.26) with Mercurial 1.0.1
Thanks

You're seeing those changes because whitespace changes count. If you do hg diff --ignore-space-change you'll see something more like:
+ if($condition) {
line 1
line 2
line 3
+ }
which sound like what you want. You can also use the ExtDiff Extension to call any of the alternate diff programs #sarnold suggests.
Also, consider updating Mercurial. Your version is about three years old and current packages are built for Debian.

I was interested in something similar, but I ended up using DiffMerge (Windows only, but you can try Kdiff3 on Debian) as visual diff for reviewing changes like that:
Sadly, even if you generate the patch in the form you like (using other tools), in the repository history it will be shown in the standard mercurial format.

Related

Custom diff by textconv in SourceTree

I'm trying to compare and merge MySQL WorkBench files in SourceTree, and in order to do so I created a small shell script that extracts the content of the .mwb file and strips some useless counters from the XML file inside it.
Then I added this line to .gitconfig in the project's root:
[diff "mwbdiff"]
textconv = mwb-diff
and this in the .gitattributes:
*.mwb diff=mwbdiff
Now, if I change something on a .mwb, then "git diff" on console shows the correct differences, and SourceTree does it, too:
The problem is that if I try to do the same on already committed versions, I get nothing:
Same result if I try to merge. I still get the right output if I try to run GIT from the console like this:
git diff develop feature/four -- test.mwb
but if I try to merge, then I get unsolved conflicts and I don't know how to proceed.
I also tried to move the .gitattributes and .gitconfig changes into the global variables, and it actually works in the console, but it didn't help SourceTree.
I suspect it has something to do with the binary preview in SourceTree (Mac version), if I could disable it...
What am I missing? How can I solve this problem?
I think that this is not supported.
So to avoid calling git diff when it will ultimately just produce no output, SourceTree pre-detects whether files are binary or text on the disk, identified by whether in a quick sample of the initial chunk of the file contains a couple of binary zero's in succession. I can only assume that the odt formats include this sequence, so SourceTree treats them as binary. On Mac we have a binary preview pane which displays before/after of supported binary files but we haven't ported that to Windows yet.
At the moment we don't support your case and may not add it in the near future, because it's a pretty rare thing to do and most people would just see a performance penalty when git diff fails and we then fall back on other techniques. We'll keep this logged for possible future support.
Source: JIRA - textconv diff not generated
So in other words, SourceTree specifically avoids calling git diff for files that SourceTree considers to be binary. That means that any textconvs don't get called at all.
The only way to work around this would be to trick SourceTree into thinking that your file isn't binary. Which is probably not feasible.

How to merge in mercurial by TortoiseHG?

I have two machines, window 7 with TortoiseHG 2.6 and Linux with TortoiseHG 1.5. I use bitbucket as a website to hold my centralized repository. The window machine associates with bitbucket user account, Cassie-win and the linux machine associates with bitbucket user account, Cassie-linux. Here are the steps I have performed.
created a empty centralized repository at butbucket Cassie-linux account
create two files locally, file1.txt and file2.txt on linux machines and push them to the Cassie-linux account.
Add user Cassie-win to the repository
Clone the repository to the window machine, make changes on file2.txt there and push it back to the centralized repository.
Meanwhile, also make some changes on the file2.txt which is on the linux machine and commit locally
Then I pull changes from the centralized repository at Cassie-linux account to my local linux machine. Now my linux local repository has two heads because of different contents in file2.txt and I would like to merge them together.
I used the "merge with" tool of TortoiseHG on my linux machine to merge these two heads. However, it kept failing to do so. I tried like a hundreds times and didn't know where I got it wrong. Both file1 and file2 are test files that have only three lines. I also used a command "hg resolve file2.txt" to check the error. However, it only showed that mergeing fails and didn't shown much information. Does anyone know how to use TortoiseHG merge tool to merge two heads ? And what could be the problem to stop TortoiseHG merging two heads ?
I embedded the screenshot which I took on the Linux machine which has TortoiseHg 1.5.
I right clicked the "from Cassie-win account" and it has "merge with" option. Then, I clicked the "merge" option with "merge" tool but it failed with error messages as below.
Thank you very much,
By "merge with" in TortoiseHg, do you mean you tried "Merge with Local" from the context menu of one head after updating your working directory to the other head? If so, you should have seen a wizard taking you through the steps of a merge. TortoiseHg will expect you to intervene if it cannot automatically merge the two heads. Once it asks you to do that, you have a few options including "Mercurial Resolve" and "Tool Resolve."
If you could post more details about the errors you see when the merge "fails," we might be able to be more helpful.
First things first: A merge just creates a new file version. You must commit it before it can be seen or pushed to your other repo clones.
Now, if you're doing a merge and the same line, or adjacent lines, have been modified in both merge parents, the automatic merge won't succeed and you'll be asked to choose what to do at each conflict point. Kdiff3, the tool that TortoiseHG uses for merging the files on Windows is not terribly intuitive, so here's an overview:
If there are multiple files to merge, you'll see a directory control. Navigate to one of the files and open it so you see two file versions side by side.
Depending on the circumstances, you may now have to activate "Merge this file" (in the Merge menu and on the toolbar), which will show you a third version of the file (the merge result) below the other two.
You can now navigate from change to change, and click on the A and B buttons to select which change to use. Note that the buttons are toggles, and it is possible to activate both together (to import both versions to the merge). Note also that you'll also see diffs that could be automatically merged. In general you can leave them alone (there are navigation buttons that go directly to the next unresolved diff).
Once you've figured out how to work all this and chosen a version for each diff, you'll be able to save and go on to the next file. When you're done, your merge is ready to commit.
Edit:
So you need to do this on the Linux side, and you've got no Kdiff3. Ok, then do it the old-fashioned way: Using the commandline and a regular editor.
When a merge fails, the conflicted file turns into a context diff that includes both revisions. Open it with your favorite editor, look at it carefully and clean up each context-diff region (you'll know them when you see them) until you have a clean, usable file just as you want it to be.
Exit, drop to the command line and type hg resolve -m file2.txt. This removes the file from the list of conflicts.
When you've done this with all conflicted files (you can list them with hg resolve -l) you'll be allowed to commit, and your troubles are over.
PS. If you don't like the merge tools you've got, consider installing kdiff3 (it's available for linux, but no idea how well it works), or p4merge as #LazyBadger suggests.
Side notes
You can exchange data between your hosts without "Bitbucket-in-the-middle": just hg serve on both hosts and hg pull <PARTY> on opposite side
You could use single BB-account from both our hosts (less management on BB-side) and differentiate source of every changeset in Bitbucket interface only by usernames in changesets
To the question of merges
When (in any SCM) you try to merge two diverged lines of coding, there are two possible cases
Independent changes are not overlapped and can be combined into common descendant without user's intervention. If this case merge "just happens"
Changes are intersected and some strings are in conflicted state: i.e we have two different changes for some old data. It this case user's choice is needed and SCM or store merge-result with conflicted parts marked (and note merge as unsucceful and unfinished before appropriate user-action) or run user-defined merge-resolver (read "Visual Merge Tools")
In your situation, obviously, he have second case: some strings from 3 in merge-sources was in conflict and you haven't configured in TortoiseHG Diff/Merge tools (TortoiseHG - Global Setting - TortoiseHG)
Have and add these tools will be best choice for future. Now you have by hand edit file-in-conflict and select correct data in conflicted lines, mark conflict as resolved (check TortoiseHG context menu of file), remove temp-files and, at last, commit merge

How resolve this Mercurial conflict?

I'm frustrated with Mercurial and Python since it makes easy things difficult. I have a trivial conflict and since Mercurial does not give any suggestion what to do I don't know even how to resolve this trivial file conflict:
The conflict is trivial but if I can't resolve this I can't resolve anything complicated either. Can I just edit the file to a way I want and commit it again from anywhere? Should I run hg merge? Why can't Mercurial even let me choose a version to keep? Why is something trivial near impossible to do without digging through 1000 poorly written manpages?
You need to look at the KDiff3 documentation, in particular the section on merging and the output window. To resolve the conflict, you need to decide if live or january is the right choice for the line. That decision is yours to make, no tool can know if you meant one or the other.
In KDiff3, you press Ctrl + 2 to select live, press Ctrl + 3 to select january or right-click in the margin of the bottom window and select the line you want. You can also click in the bottom window and edit the line manually.
Mercurial let's you configure your merge tool any way you like. TortoiseHg ships with a default configuration that puts KDiff3 in the top of the list, but you can use another tool if you like. A merge tool is really just a program that accepts four filenames: the three files to compare (base, parent 1, parent 2) and an output file name.
To resolve conflicts on the command-line you need to launch a suitable command-line three-way merge tool. You can for example merge with vim if you like. (I'm afraid I don't know anything about vimdiff, I use KDiff3 myself.)
If you don't like to see merge tools pop up, then you can set
[ui]
merge = internal:merge
to make Mercurial use the internal three-way merger only. It will merge files fine when the edits are not in conflicts. When there is a conflict, the file is marked as "unresolved" and conflict markers are stored in the file.
You then need to edit the file by hand to get the version you want. You can also re-merge and pick either the local (your) version:
$ hg resolve --tool internal:local your-file
or the other version:
$ hg resolve --tool internal:other your-file
You restart the merge completely with hg resolve your-file. The file needs to be marked "resolved" before you can commit it. This is done with hg resolve --mark your-file. See hg resolve --list for the status of the current merge.
Base is the previous version in your local system,
Parent 1 is your current changes,
parent 2 is the file from server.
If you need your changes need to be checked in, select B everywhere in the merge menu.
If you want the latest server version in your local machine, select C everywhere in the merge menu

mercurial fails with a file named ---.config - any way around this?

We are just beginning to learn and evaluate Mercurial, due to an increasing number of nightmare merges, and various other problems we've had with SVN lately.
A client wants us to pull down a live copy of their site, do some SEO work on it, and push it back to them. They have no source control at all. I figure this is a great project to work on with Mercurial. Instead of putting it into our SVN and exporting when we are done, we'll use Mercurial... But right away it seems I have some problem :)
They have a file called ---.config which seems to cause our Mercurial to barf. It just can't commit that file. I've created the repo and committed everything else, but I just can't get this one file committed.
We are running on Windows 2008 x64 with TortoiseHG 1.0.
I suppose I could ignore the file since it is unlikely we'll need to work with it, but still - I'd like to learn how to use Mercurial a bit better. Is there a way around this?
EDIT: here is the error message:
('commit', GetoptError('option ---.config not recognized', '-.config'))
This happens when I hit the "commit" button in TortoiseHG with that file selected.
Not sure about hg, but most command line tools treat anything after a -- as a non-option. This is helpful if you have a filename that starts with -- or a wildcard that picks up such a file; try prefixing your filename or wildcard with --, e.g., hg command -- *.config.
The problem is that TortoiseHg did not escape filenames correctly when calling hg. When a filename starts with --, one must take extra care when using it on command lines.
I have just sent a patch which will hopefully make it into TortoiseHg 1.0.1, which is scheduled to be released later today.

Mercurial performing binary comparison for certain file types [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does Mercurial think my SQL files are binary?
I've recently started using Mercurial and when I reverted one of my .SQL files, Mercurial performed a binary comparison. This obviously limits the visibility of the changes that were made, as there is no diff.
Is there an option to set file types to do a string compare?
I'm using Tortioise Hg 0.8.1 with Mercurial 1.3.1.
Mercurial doesn't actually handle text and binaries at all differently with respect to actual storage. It does however try to guess "would visually showing this diff be meaningful" when asked to show a diff to a user with hg diff, hg log -p, or when viewing a changeset in the web interface. When it's trying to make the "should I show this as if it's text" decision the test applied is "Is there a NUL byte (0x00) within the first 1000 bytes of a file.
So your file isn't being treated any differently except in how it's displayed to user output, but if you can find a NUL byte in there you can probably get that to stop too.
Alternately, the extdiff extension can be used to take total control of how diffs are displayed.
I don't know about the graphical part of TortoiseHg, but if you use the command line, then the --text flag to hg diff should do the trick: it makes Mercurial treat all files as text.
You should try adding these lines to ~/.hgrc:
[diff]
git=1
The git diff format works for binary files.