How to show full paths in git diff? - git-diff

How do I show full paths in git diff?
One can use '--dst-prefix=$PWD' and '--src-prefix=$PWD' but this is fragile as it won't work in many cases, eg with --no-index, or when running the commond from a subdirectory without using --relative=realpath_to_cwd

It should be possible to:
get the the path of the root folder of the repo: see "Is there a way to get the git root directory in one command?"
use that path in the --relative, --dst-prefix and --src-prefix options.
That would be more robust than $PWD.

Related

Folder capitalization not changing on branch switch

I'm working on a python project and want to rename a (package) folder to small letters, let's say from Myackage to mypackage. As git is case-sensitive and Windows is not, I followed the solutions taken from here and espacially here.
My procedure was as follows:
git mv Mypackage tmp
git mv tmp mypackage
git commit -m "Change capitalization of package name"
This changes the folder Myackage to mypackage with success (for both, git and Windows). But if I switch to another branch, I expect the folder to change back to Mypackage (with capital letter!), as it was before. Background is, that all the imports of the package are also case-sensitve in python and i need this renamng acompanied with adaptions of the imports.
I've tried both, core.ignorecase set to true and false, but no matter what I try, if I checkout an older branch, the folder remains in form of small letters (mypackage) and I run into issues within python.
UPDATE:
I've set up a small example with only one Folder and one file and could succesfully change the capitalization of the folder. It also shows the desired behaviour, that upon branch switch the capitalization of the folder in Windows changes, yet still this won't work for my python project.
Could it be, that, e.g., submodules, play a role here?
UPDATE 2:
I've checked the case sensitivity attribute for both cases via:
fsutil.exe file queryCaseSensitiveInfo .
Both folders claim, that case-sensitivity is deactivated. Still for one project folder name capitalization changes, but for the other folder not.
The attribute case sensitivity is available on Windows 10 but after April 2018 Update and only affect the specific folder to which you apply it. It isn’t automatically inherited by that folder’s subfolders. However, if you use WSL to create folders it's enabled by default and available in that way to Windows. [1]
Although you can use the Git Unite [2] tool to match the case of the current folders with the git index.
If you use the rename approach, try using it with git commands like in "Rename files and folders with git"[3]
git mv foldername tempname && git mv tempname folderName
I found a way to reproduce your behavior :
if my CaSeD folder contains some extra files (untracked files for example), git will not change the case of my folder name when I jump between commits.
Is this the case in your setup ?
If this is your issue : you could go with a post-checkout hook, which forcibly renames the folders according to what is stored in HEAD after a checkout.
One way to get the full list of paths to directories from commit HEAD is :
git ls-tree --name-only -d -r HEAD
If you match this list with a similar list extracted from your local file system (ls -r ? find . -type d ? some python function from os.* ?), you can spot what folders need to be recapitalized.

How to change SYMLINK to SYMLINKD in batch script

We're sharing SYMLINKD files on our git project. It almost works, except git modifies our SYMLINKD files to SYMLINK files when pulled on another machine.
To be clear, on the original machine, symlink is created using the command:
mklink /D Annotations ..\..\submodules\Annotations\Assets
On the original machine, the dir cmd displays:
25/04/2018 09:52 <SYMLINKD> Annotations [..\..\submodules\Annotations\Assets]
After cloning, on the receiving machine, we get
27/04/2018 10:52 <SYMLINK> Annotations [..\..\submodules\Annotations\Assets]
As you might guess, a file target type pointing at a a directory [....\submodules\Annotations\Assets] does not work correctly.
To fix this problem we either need to:
Prevent git from modifying our symlink types.
Fix our symlinks with batch script triggered on a githook
We're going we 2, since we do not want to require all users to use a modified version of git.
My limited knowledge of batch scripting is impeding me. So far, I have looked into simply modifying the attrib of the file, using the info here:
How to get attributes of a file using batch file and https://superuser.com/questions/653951/how-to-remove-read-only-attribute-recursively-on-windows-7.
Can anyone suggest what attrib commands I need to modify the symlink?
Alternatively, I realise I can delete and recreate the symlink, but how do I get the target directory for the existing symlink short of using the dir command and parsing the path from the output?
I think it's https://github.com/git-for-windows/git/issues/1646.
To be more clear: your question appears to be a manifestation of the XY problem: the Git instance used to clone/fetch the project appears to incorrectly treat symbolic links to directories—creating symbolic links pointing to files instead. So it appears to be a bug in GfW, so instead of digging it up you've invented a workaround and ask how to make it work.
So, I'd better try help GfW maintainer and whoever reported #1646 to fix the problem. If you need a stop-gap solution, I'd say a proper way would be to go another route and script several calls to git ls-tree to figure out what the directory symlinks are (they'd have a special set of permission bits;
you may start here).
So you would traverse all the tree objects of the HEAD commit, recursively,
figuring out what the symlinks pointing at directories are and then
fixup the matching entries in the work tree by deleting them
and recreating with mklink /D or whatever creates a correct sort of
symlink.
Unfortunately, I'm afraid trying to script this using lame possibilities
of cmd.exe-s scripting facilities would be an exercise in futility.
I'd take some more "real" programming language (PowerShell as an example,
and—since you're probably a Windows shop—even a .NET would be OK).

Git on Windows capitalized file names on origin, lower case locally

We are forced to work on Windows at work, and I have lets say problem, strange situation. We have github repository, inside which we have one directory with name Something (with capitalized first letter 'S'), but in my local I see this directory with name something (note lower case 's'), git status shows that working directory is clean, even if I change this directory locally to, for example SoMeThInG git says that nothing changed. I suspect that Windows is here a problem, as it is case insensitive. Is there possibility to change this directory name from Windows level? Or maybe how to force git bash to be case sensitive?
Update
I've changed that files from mine virtual fedora, but this is just a workaround, the question remains unanswered, how to do it properly on Windows?
On case-insensitive file systems, Git will not detect changes just in casing. However, when committing files, the actual casing is still being reflected in the way it was added to the index.
So a git add file and git add FILE will both work for a file that is named file in any kind of casing (e.g. FiLe or fIlE), but each command will actually stage that exact name into the repository. So git add file will make the name be case-sensitive file and git add FILE will make the name case-sensitive FILE.
That’s why you should try to always use your command line auto completion for file names, so you don’t accidentally add files with a different casing than they actually are. Or use commands that stage the files automatically, e.g. git add ., since that will also use the actual casing.
However, since Git will not detect casing changes, once a file has been added with a particular casing, that casing will be used until you explicitly change it. That’s why it’s possible to have files in a folder src/readme.md and SRC/license.txt that are both physically in the same location on your file system, but are represented using incompatible paths inside of Git. So you should be careful here.
That all being said, you can fix the casing later. But to do that, you need to make the change using Git instead of the file system, as Git is case sensitive while the file system isn’t. So commands like git mv will work. Same as a combination of git rm --cached and git add.
For example, to fix the above situation of the src/SRC directory, one could do (assuming the correct name of the folder should be Src):
git mv src/readme.md Src/readme.md
# or
git rm --cached SRC/license.txt
git add Src/license.txt
You can also fix the casing for every file by removing everything from the index, and then adding it back:
git rm --cached -r .
git add .
That should stage all renames to the correct file casing.

Can't use git add with --patch option

I recently updated Git to version 2.7.2.windows.1 (I am running Windows 7 64-bit). Since the update, I have been unable to run git add with the -p option on files within a certain directory (or its subdirectories) whose name is _ (an underscore).
git status correctly reports that my file has changes:
PS C:\Users\Carl\www\dl> git status
On branch develop
Your branch is up-to-date with 'origin/develop'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: _/php/class.Menu.php
And I can add the entire file with a simple git add, or by specifying the file by name. But if I try to include the -p or --patch option (both variations produce the same results), Git reports that there are no changes:
PS C:\Users\Carl\www\dl> git add -p .\_\php\class.Menu.php
No changes.
This only happens for files within the _ directory, but it doesn't matter whether I cd into that directory to run the git add command without having to explicitly specify a path with an underscore in it; it still doesn't work:
PS C:\Users\Carl\www\dl\_\php> git add -p .\class.Menu.php
No changes.
I had initially thought this problem was related to a similar one I encountered recently on files within the _ directory, which I asked about here. However, that problem appears to have been related to Posix path conversion in MinGW, whereas this problem occurs whether I use Git Bash, Windows PowerShell, or cmd.exe.
As I said in that previous question, I believe underscores to be valid in file/directory names. Additionally, I am not the owner of the project so I cannot rename the directory or move the file.
Is this a bug in Git? Are there any additional steps I can take to determine what the underlying issue is?
Well, I was able to reproduce this, and seems that it is the same POSIX-to-Windows path conversion. ProcessMonitor shows that git (actually, perl run by git) looks for a file C:\Program Files\Git\php\class.Menu.php.
To work this around (at least, that worked for me), according to documentation, you can set the environment variable MSYS_NO_PATHCONV temporarily, like so (in git bash):
MSYS_NO_PATHCONV=1 git add -p _/php/class.Menu.php
(I don't know how to set env variables in windows' cmd/powershell, but that should be possible, too.)
You shouldn't enable MSYS_NO_PATHCONV globally/permanently (e.g. using export in git bash or modifying windows' user/system environment variables in system settings), because that can lead to unwanted effects, and it'll probably break much more things than it'll fix (see this SO comment). Actually, git-windows folks warn against even temporary enabling MSYS_NO_PATHCONV.
Having said that, I'm starting to think that OP's problem is a git-for-windows bug and should be reported as such (might have something to do with the fact that git-add is a binary, but git-add--interactive is a perl script).
Another listed workaround is to double the first slash, like git add -p _//php/class.Menu.php (or does that mean the parameter must start with a double slash?), but that doesn't seem to work due to complex intermediate path conversions, that happen between the invocation of git add and the real file access.
I'd try without that .. Also I've never passed a filename to git add -p. I just make my change and run that as is. I would also check to make sure any changes you're making are in fact being applied to that specific file, and the file is being touched.

Change case of a file on Windows? [duplicate]

This question already has answers here:
How to make git ignore changes in case?
(6 answers)
Closed 10 months ago.
There are a couple of files in our git-controlled codebase that I'd like to rename. Specifically, I just want to change the case of the file, so that sourceCode.java becomes SourceCode.java, for example. The catch: I'm on a Windows box, and the filesystem thinks those are the same file name.
How can I get Windows and Git to recognize that change and check it in?
The change of the file name should not be ignored, but committed to git.
To rename the file you can use the standard git mv command.
Since Windows treats files with only changes in case as identical, you have to pass the -f option to force a rename:
git mv -f name.java Name.java
If instead you want to ignore case changes, have a look at the question
How to make git ignore changes in case?.
If you are on a FAT file system your only choice is to do a two stage rename:
Rename sourceCode.java to anything.you.like
Rename anything.you.like to SourceCode.java
Back in the days when we used Perforce we had exactly this problem and this was the only solution we could come up with.
The following steps allowed me to change the case on Windows:
Add ignorecase = false to [core] in .git/config;
Move the files you are going to rename out of your project directory;
Add the deletes to the index;
Move all files back to their original location and change the case of the files and/or directories;
Add all "new" files to the index;
Remove ignorecase = false added at the first step.
This way you have a single commit that contains the rename and it makes it easy to change e.g. an entire directory.
In my opinion one simple way is missing. You can do this for a single file, a specific directory or even the whole repository. Just rename your files in any way you like before and than execute these commands:
git rm --cached <file name or directory>
git add <file name or directory>
If you want to affect also the sub-directories, you have to use the -r flag:
git rm -r --cached <directory>
git add <directory>
Be careful. Doing this can lead to changes that are impossible to merge. Git gets confused when merging on Windows because it can't decide whether the old Uppercase name and the new lowercase name are the same file or not (for Git they are not, but for the filesystem they are). To merge you have to do some manual workaround like deleting the files before merging.
See Git rebase issue with files of same name but different case
I'm not sure if this issue is worse than having an unconventionally-named file in your project for ever and ever, but it is worth knowing about if there are lots of users with lots of branches which will all need to be merged eventually.
With NTFS (or FAT), a single git mv command does not solve the problem.
This question shows a technique that works:
git mv and only change case of directory

Resources