Avoid Git to do any merge to a certain filetype - merge

I am working on a quite big project versioned on a Git repositories that have several file of different types versioned. Among those, we use the QM Modelling tool that uses .qm files, which are actually xml files with a certain structure.
The structure of the .qm and the meaning of its content makes it unadvisable to use a merging tool to merge any change.
What I would like to do is have git issue a conflict in case it finds changes to any qm file even if it could merge those changes ( even if it could, the result is not guaranteed to be meaningful ), so that I can manually merge them using the tool.
Pros if the same is true if I perform a rebase instead of a merge.

Ok, answering myself as I found a solution.
I found this answer and modified it a little bit. I added a new merge strategy that basically takes the file as it is in the incoming branch and uses it untouched, then marks the file as with conflict.
So i created this script:
#!/bin/bash
# ${1} is the base common file
# ${2} is the file as modified by the base branch, and where the results must be
# ${3} is the file as modified by the incoming branch
# ${4} is the path of the file being merged
# ${4%.qm*} is the path without extension
# ${4##*.} is the extension of the path
# makes a backup of the original file to ease edits comparison
cat "${2}" > "${4%.qm*}.bk.${4##*.}"
cat "${3}" > "${2}"
exit 1
which uses the incoming file as a result as it is, and returns 1 to mark it as conflict.
Then I added in the .gitattributes the option to use this strategy for my .qm file, so that when I merge two branches, I take the incoming version as it is and use the graphical tool to modify and integrate my changes.
I'm going to leave this question as unresolved to see if anybody got another solution that would enable me to use both rebase and merge.
EDIT: I updated the script, I added a few lines to take the version of the local branch and make a backup of it, so that it is available to use in a comparison tool to identify my changes more easily.

Related

How can I use "cleartool merge" to merge from a checked out version on another branch

I have file checked out in a view, on its default branch:
/main/pdb8.1/fq05-ae002.4/CHECKEDOUT
I have another view which creates a branch off of fq05-ae002.4 called ae002.4-test2.
I have the file checked out in that view as well:
/main/pdb8.1/fq05-ae002.4/ae002.4-test2/CHECKEDOUT
I made a change to the checked-out version on the first branch, and want to merge it into the second branch. I know how to do this via the VTree browser in Windows (and Unix), but I would like to know how to do it from the command line. These files and vobs are large, and loading the VTree takes forever.
I already know how to do it if the file is checked in on the first branch (e.g. version 2):
ct merge -to myfile -insert -version /main/pdb8.1/fq05-ae002.4/2
ct mkhlink -unidir Merge /vobs/{vob}/path/to/myfile##/main/pdb8.1/fq05-ae002.4/2 myfile
But I guess I'm not sure what to put in place of /main/pdb8.1/fq05-ae002.4/2. The CHECKEDOUT.464646 doesn't work.
It is not generally possible to merge FROM a checked out version. If you can start both views and access the checked out version that way, you may be able to use the merge tool to merge them that way, providing the paths for the and from versions.
Is there some reason you can't check the source version in first?

How to freeze a file for changes but leave it in the repository using Mercurial

Quite often I have a situation like the following:
some Hg repository with a bunch of configuration files that are shared
some configuration files contain passwords, that should not be shared, they are local to the user
I would like to keep a version history on these files, but they will only occasionally be updated. It is annoying if every time you do a commit or merge or update you have to remember that you do not want to commit your locally changed password.
How can I freeze a file in the repository (and conversely, for the occasional legitimate update, unfreeze it) so that it does not appear in the commit list, but does appear as versioned in the repository and everyone can share a base copy?
This question gets asked a lot, and the answer is always the same: there's no good way to do what you want. A file that's tracked is tracked for all changes.
The setup everyone settles on is committing a configurationfile.example to the repo where changes everyone needs are shared, and add configurationfile to your ignore. If you're savvy you then have your launch script copy configurationfile.example to configuration location if it doesn't already exists. If your configuration format is flexible enough to support an include (most are these days) you have you configurationfile committed and have it do an include of a non-tracked (ignored) configurationfile.local where people override things. This is how everyone does it in both git and Mercurial.
-X option for commit, none (easy) for merge
-X --exclude PATTERN [+] exclude names matching the given patterns
i.e most times you commit hg ci -X FILENAME, sometimes - pure hg ci. You can define hg ci -X FILENAME as new alias and use two different commands for different commits
In case of merges you can try to define for config-file special merge-tool (provably internal:local or internal:fail)
Anyway, you selected wrong and error-prone method of storing local configs as shared common files. (Viable) alternatives may include (in order to name a few)
Config.TEMPLATE in repository and modified for local needs hgignore'd Config
LocalBranch, in which you store code with location-specific changes
MQ extension (somehow related to 1-st solution) - repository stored "vanilla" config, all local-only changes placed in MQ-patch

Merge/diff tool that can show authors (supports blame or annotate) in files under version control

When merging files it will be helpful (as for me) to show an author of each line. Is there any diff or merge tool supporting that?
The bundled gitk tool is not really a merge tool, but it shows conflicted lines with red and blue and "+"'s in front, and you can Rightclick->"Show origin of this line" on any of them, to go to the commit which introduced the line:
You can run your mergetool, or just a text editor with diffmarks in parallel
So what you really want is a tool that can easily identify your changes
relative to other's changes in a merge conflict, rather actually identify
the author of each line (which would be a mean to achieve that), right?
If I understood you correctly, I have some relatively good news: It
can be done with git + kdiff3. For merging you can just use git mergetool
(which you can configure to use kdiff3). But it is not supported natively
if you get a merge conflict when doing interactive rebase, so for that
some manual scripting is required.
Instead of making up my own simple merge conflict example, I will use
http://www.gitguys.com/topics/merging-with-a-conflict-conflicts-and-resolutions/
as an basis. Follow that page to git merge test. From after the merge
command I diverge a bit from that example by running different commands
(but basically doing the same job). I'll do all the manuall steps first.
So we have a merge conflict and git has inserted content from both
contributing sources into the file in this <<<<<<<...>>>>>>> format,
which I really do not like at all and never consider even looking at it.
Instead I use my favourite merge tool, kdiff3.
First we need to find which versions that are involved.
$ git ls-files -u
100644 b0ed415d15862ac5582b51e4de65528e86934cd2 1 README
100644 56300e3ac4e4521c3500618a301bb2ab2d6a52f5 2 README
100644 9585db7d9c2d9ca05075f67a878f2554886d7b1a 3 README
$
Basted that information we can perform a three way merge:
$ git cat-file blob b0ed415d15862ac5582b51e4de65528e86934cd2 > v1
$ git cat-file blob 56300e3ac4e4521c3500618a301bb2ab2d6a52f5 > v2
$ git cat-file blob 9585db7d9c2d9ca05075f67a878f2554886d7b1a > v3
$ kdiff3 -o merge_result v1 v2 v3 &
[2] 18394
$
Which gives the following view where you can select from which ancestor
you want to merge from.
Afterwords (if you are satisfied with the merge result)
you need to
$ rm v1 v2 v3
$ mv merge_result README
$ git add README
All the manual steps above are done automatically with git mergetool.
So why showing all that then? Well, because if you get a corresponding
conflict during git rebase -i, then it has to be done that way (before running git rebase --continue).
In this small example there is only one conflict
line, so it does not show the more typical case where a lot of lines
are automatically resolved, leaving you to just manually resolve the
ones that was not done automatically.
A more real life example might look more like the following:
Notice that in the merge result you now clearly see the origin of the C lines that
were automatically resolved. I think this is sort of what you were asking for when asking for getting the author for each line, right?
That information is completely absent in the <<<<<<<...>>>>>>> text (and it is difficult/impossible to spot that you should update the printed string in the hello function).
I cannot recommend kdiff3 highly enough. Using a graphical merge tool like that compared to some lines from both sources mixed inline in the file is like using an excavator versus a spade.
No. And, I think, never will be - when we merge, we think about content, not authorship

Exclude a config file from the merge process

Is there a way to exclude a specified file from the merge process? when merging from our production branch to the test branch for the testers to use, we want to exclude a config file which contains the SQL connection string. Preventing the need to edit it post merge. I did see a comment about using the cloak option but i can only see this available for folders not files.
Tim
There are a few different ways you can do this. If you don't plan on changing your config file in the future and you just don't want its current contents to make it to the parent branch, you could simply do a "tf merge /discard" on the file and check that in. That basically says, never merge the changes that have happened to this file to the target branch. However, if the file changes again, it will be a candidate for a merge.
So, if you plan on continuing to change the config file in question, then you have two options. The first is to always cloak this file in the target branch workspace that you are performing the merge in. Yes, it is possible to cloak files, it is just the picker in the dialog doesn't make this easy. If you navigate all of the way down to the containing folder, select that and then manually enter the file name at the end of the folder string, the cloak will work on the file. This approach has the downside that you have to remember to always cloak this file in the workspace that you are performing the merge in and if someone forgets to do that, the file will be merged up.
The third, and likely best, solution to this problem is to use the tfpt.exe power tool with the branches command to cloak the config file from the parent's branch mappings. You can download the latest 2010 power tools here. You will want to run "tfpt branches /properties /collection:" and then select the "mappings" channel. In there you will probably just see a single mapping for the root of the branch. You will want to create a cloak mapping for the file you do not want to be merged and then click OK. On all subsequent merges to that branch (note, from any other branch) the file in question will not be merged.
Not a very nice solution, but you could remove the checkin security on that file so you are unable to checkin the file after a merge.

Mercurial: How to ignore changes to a tracked file

I have a file with database settings in my project which I have set to some defaults. The file is tracked by Mercurial and checked in. Since this file will be edited with different values various developer machines, is there a way I can tell Mercurial to ignore new changes to this file?
I tried adding the file to the .hgignore file, but since the file is tracked it isn't ignored. This is alright and good in other situations, but I am wondering if there is something I can do here?
Using a file template is definitely the best solution.
For example, if you have a database.ini file, commit a database.ini.template file and ignore database.ini in .hgignore
If you always want to ignore the file, you can add the -X option as a default for commit to your .hg/hgrc configuration file:
[defaults]
commit = -X program.conf
We wrote an extension for this called exclude. It will automatically add the -X options on the commands that support them -- so hg status and hg commit wont see the modified file. It works by reading a .hgexclude file from the root of your repository, just like the .hgignore file. You add the files that you want to exclude there:
syntax: glob
db.conf
The extension works quite well, but there is a known situation where it fails: merges and the commit that follows a merge (this is documented on the wiki). It would need to be improved so that it would save the modifications away to a temporary file and then restore them afterwards. Please get in contact if you need this feature.
There is no truly automated process, but you can try (as in this SO question) the -X option on hg commit:
% hg stat
M myfile
% hg commit -X 'myfile'
(other solutions might involve shelve or hq)
However, this is not the "right" solution. I would rather recommend versioning:
a file template
a script able to generate the final file (that you modify but can ignore altogether)
If you are using TortoiseHG, open the Settings for the repo, go to the Commit section (2nd icon down on the left) & add the file name(s) to the Auto Exclude list on the right (~ 3rd from the bottom in the list).
From https://tortoisehg.readthedocs.io/en/latest/settings.html#commit
Typically you would check in a reference copy of the file and track it then have the developers make a copy of that for local development, you wouldn't really want developers editing the source controlled file for their own environments.
If your configuration system supports it, it's even easier if you can use an override file that simply override values in the reference copy (e.g. the database connection string). That way devs only have to keep a very minimal local set of override values.
If the file is already being tracked, you can issue the Forget command to the file. If you're using TortoiseHg just right click the file during commit and select Forget. The file must also be already in the ignore list.
I had the same problem as yours, I file keeps on appearing on every commit even-though its already in the ignore list. I tried the Forget command and it did the trick.
You can try hg forget.
For more details, see the official manual about the same command.
It worked for me.
I think, something like this is closer to a correct answer to the original question Mercurial: How to ignore changes to a tracked file, rather than the others suggesting a template, etc.