Git config files: Best practice - windows

I managed somehow to make Git running with Github and now (a year later) I would like to teach the group how they can do the same. I learned quite a lot from here, but even with the answer, some things remain unclear. Please apologize, if I didn't got it from the git reference
Questions:
Is there a best practice, which parameters should show up in which config file?
... Continued from my example below:
I marked the parts which I can access via --system, --global and --local. Does anybody know where the first part belongs to?
Green is everything, where I think, it is ok (with my very limited knowledge).
Red is strange as it exists twice
When I run git config --list --show-origin I get the following result:
Edit #Code-Apprentice:
From git-bash
$ git config --list --show-origin --system
file:"C:\\Git\\mingw64/etc/gitconfig" credential.helper=manager
and cmd
>git config --list --show-origin --system
file:"C:\\Git\\mingw64/etc/gitconfig" credential.helper=manager
Git output as code:
file:"C:\\ProgramData/Git/config" core.symlinks=false # ... see .git/config
file:"C:\\ProgramData/Git/config" core.autocrlf=true
file:"C:\\ProgramData/Git/config" core.fscache=true
file:"C:\\ProgramData/Git/config" color.diff=auto
file:"C:\\ProgramData/Git/config" color.status=auto
file:"C:\\ProgramData/Git/config" color.branch=auto
file:"C:\\ProgramData/Git/config" color.interactive=true
file:"C:\\ProgramData/Git/config" help.format=html
file:"C:\\ProgramData/Git/config" http.sslcainfo=C:/Git/mingw64/ssl/certs/ca-bundle.crt
file:"C:\\ProgramData/Git/config" diff.astextplain.textconv=astextplain
file:"C:\\ProgramData/Git/config" rebase.autosquash=true
file:"C:\\Git\\mingw64/etc/gitconfig" credential.helper=manager # ... see file:C:/Users/myname/.gitconfig
file:C:/Users/myname/.gitconfig filter.lfs.clean=git-lfs clean %f
file:C:/Users/myname/.gitconfig filter.lfs.smudge=git-lfs smudge %f
file:C:/Users/myname/.gitconfig filter.lfs.required=true
file:C:/Users/myname/.gitconfig user.name=My name
file:C:/Users/myname/.gitconfig user.email=my.name#domain.com
file:C:/Users/myname/.gitconfig credential.helper=wincred
file:C:/Users/myname/.gitconfig alias.hist=log --pretty=format:'%h - %an, %ad: %s' --graph --date=short
file:C:/Users/myname/.gitconfig difftool.kdiff3.cmd='C:/Program Files/KDiff3/kdiff3' $LOCAL $REMOTE
file:C:/Users/myname/.gitconfig difftool.kdiff3.keepbackup=false
file:C:/Users/myname/.gitconfig difftool.kdiff3.trustexitcode=false
file:C:/Users/myname/.gitconfig merge.conflictstyle=diff3
file:.git/config core.repositoryformatversion=0
file:.git/config core.filemode=false
file:.git/config core.bare=false
file:.git/config core.logallrefupdates=true
file:.git/config core.symlinks=false
file:.git/config core.ignorecase=true
file:.git/config core.hidedotfiles=dotGitOnly
file:.git/config remote.origin.url=https://github.com/repo/Rettung-ZCH
file:.git/config remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
file:.git/config branch.master.remote=origin
file:.git/config branch.master.merge=refs/heads/master
file:.git/config branch.dev1.remote=origin
file:.git/config branch.dev1.merge=refs/heads/dev1
file:.git/config branch.dev2.remote=origin
file:.git/config branch.dev2.merge=refs/heads/dev2

Is there a best practice, which parameters should show up in which config file?
This is totally up to you, whether you want a setting only on one repository, on all repositories you access with your user account or on all repositories on this machine (each time of course only if not overwritten from a lower config level).
I marked the parts which I can access via --system, --global and --local. Does anybody know where the first part belongs to?
As far as I remember these are the default values of the Git for Windows client and are on (or rather above) the system settings level. You can list and change them with git config --file c:\ProgramData\Git\config --list and so on.
Green is everything, where I think, it is ok (with my very limited knowledge).
As I said, totally up to you. The local green settings are most probably only useful on the local level, yes. For me user.email for example is not set on global level on my work box, as I work on private and corporate repos and use different addresses there. By not configuring either on the global level I am reminded on local level to set it when doing the first commit.
Red is strange as it exists twice
You can have each setting on each level, lower level overwriting value of upper levels, this is perfectly legal. You can e. g. set for all users on the system to use credential.helper=manager but for your user to use credential.helper=wincred like you have it in your example.

For Windows there should be following global settings:
rem always have Linux line endings in text files
git config --global core.autocrlf input
rem support more than 260 characters on Windows
rem See https://stackoverflow.com/a/22575737/873282 for details
git config --global core.longpaths true
rem some color and diff tweaks
rem Use SVN's ||| also in git
rem See https://git-scm.com/docs/git-config#Documentation/git-config.txt-mergeconflictStyle for details
git config --global merge.configStyle "diff3"
git config --global color.diff.new "green bold"
git config --global color.status.updated "green bold"
git config --global color.branch.current "green bold"
rem Sort branches at "git branch -v" by committer date
git config --global branch.sort -committerdate
(The hints at https://stackoverflow.com/a/24045966/873282 are obsolete)

Git will override more global settings with more local ones. The duplicated (red) ones in your output guarantee consistency at a more local level if the more global value is ever changed.

Related

Git does not recognise files with umlauts correctly on Windows 11 after migration from Mercurial

I try a migration from a Mercurial repository to Git on Windows 11 in the following way in Git Bash:
MINGW64$ ls
hg-repo/ git-repo/
MINGW64$ cd git-repo
MINGW64$ git init
MINGW64$ ~/fast-export/hg-fast-export.sh -r ../hg-repo/ --force -A ../hg-repo/authors.txt -M main
The migration succeeds and the following is needed
MINGW64$ git checkout main
which should result in a repository with no changes. But instead I get something as the following:
MINGW64$ git status
On branch main
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: Folder1/grünes-Ding.png
Untracked files:
(use "git add <file>..." to include in what will be committed)
Änderungen/
Folder1/grünes-Ding.png
So it looks like "Folder1/grünes-Ding.png" was deleted and then added again. If I try to restore the folder I get the following.
MINGW64$ git restore Folder1/grünes-Ding.png
error: pathspec 'Folder1/grünes-Ding.png' did not match any file(s) known to git
I think in this case Git does not understand "Folder1/grünes-Ding.png" because ü is represented in another way in Git as I see it in git-bash.
"Änderungen/" should be also in the repository. Because if I delete it in the working directory, it appears with all its files as "deleted" changes. If I then try to restore these files I get the same error type. The files in this folder does not contain umlauts.
My question is: How can I tell Git to handle folders and files with Umlauts?
The only thing I found so far regarding umlauts was showing them correctly in logs or commit messages. But this is not the problem here.
My config of Git looks like this:
MINGW64$ git config -l
diff.astextplain.textconv=astextplain
http.sslbackend=openssl
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
core.autocrlf=input
core.fscache=true
core.symlinks=false
pull.rebase=false
init.defaultbranch=main
difftool.sourcetree.cmd=''
mergetool.sourcetree.cmd=''
mergetool.sourcetree.trustexitcode=true
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
core.quotepath=false
core.fsmonitor=true
i18n.logoutputencoding=UTF-8
MINGW64$ locale
LANG=en_GB.UTF-8
LC_CTYPE="en_GB.UTF-8"
LC_NUMERIC="en_GB.UTF-8"
LC_TIME="en_GB.UTF-8"
LC_COLLATE="en_GB.UTF-8"
LC_MONETARY="en_GB.UTF-8"
LC_MESSAGES="en_GB.UTF-8"
LC_ALL=
I played a little bit around with the options of hg-fast-export and found a solution, eventually.
hg-fast-export has two options handling the encoding: -e and --fe. -e defines the encoding of the commit messages and author names etc. in Mercurial to convert it to UTF-8 and --fe defines the encoding of the filenames.
I tried different encodings for the filenames and found that latin1 worked for me. But first, I made the mistake to use -fe instead of --fe. But -fe results in -f and -e and not --fe. So be aware of this! If you use -e, also the option --fe is automatically set to the value of -e which then results in wrong encoding of commit messages.
Finally, the migration works like this
MINGW64$ ls
hg-repo/ git-repo/
MINGW64$ cd git-repo
MINGW64$ git init
MINGW64$ ~/fast-export/hg-fast-export.sh -r ../hg-repo/ --force -A ../hg-repo/authors.txt -M main --fe latin1

How do I remove duplicate Git config values that contradict each other?

I tried to remove the values (to reset them) but they won't go away. Plus they contradict each other.
C:\Users\Chloe\workspace\app>git config --unset-all core.autocrlf
C:\Users\Chloe\workspace\app>git config --unset-all core.editor
C:\Users\Chloe\workspace\app>git config --unset-all core.edit
C:\Users\Chloe\workspace\app>git config -l | grep autocrlf
core.autocrlf=true
core.autocrlf=false
C:\Users\Chloe\workspace\app>git config -l | grep notepad
core.editor=/C/Program Files/Notepad++/notepad++.exe
core.edit=C:\\Program Files\\Notepad++\\notepad++.exe
I tried to edit the values with git config -e (but first I had to figure out how to specify the path correctly), and it didn't list either of those config keys.
git version 2.16.3.windows.1
I found this answer http://stackoverflow.com/questions/2114111/ddg#2115116
And I used git config --list --show-origin then edited the files manually (from an elevated Notepad++). I had
file:"C:\\ProgramData/Git/config" core.autocrlf=true
file:C:/Users/Chloe/.gitconfig core.autocrlf=false
file:C:/Users/Chloe/.gitconfig core.editor=/C/Program Files/Notepad++/notepad++.exe
file:C:/Users/Chloe/.gitconfig core.edit=C:\\Program Files\\Notepad++\\notepad++.exe
Overall it was looking in 4 places: C:\ProgramData\Git\config, C:\Program Files\Git\mingw64\etc\gitconfig, C:/Users/Chloe/.gitconfig, .git/config.
Run git config -l --show-origin to see where from the settings come. Most probably from the global ~/.gitconfig so remove them with
git config --global --unset-all core.autocrlf

git stash leaving modified files?

I'm getting some odd behavior when trying to stash changes. I'm not a git expert so I'm hoping someone can shed some light on this:
On an up-to-date branch, I modify a tracked file. git status shows it as modified
git stash (responds with "Saved working directory and index state WIP on...)
git status still shows the file as modified, but git diff (and git gui) show no changes.
git stash list shows the stash was created
git stash pop responds with "error: Your local changes to the following files would be overwritten by the merge:"
The behavior at 3 makes no sense to me. It started happening fairly recently. I've been using stash/stash pop for several months with no problems.
I wondered whether there was an issue with my local working copy so I re-cloned but get the same behavior.
Is my GIT installation broken, or am I missing something?
Additional info:
Tried this on another PC and it behaves as expected, so it's something to do with this installation.
Tried creating a new local repo, add & commit 1 file, modify, stash. Same behavior
Tried with files with CR LF and LF line endings. Same behavior
git config -l:
core.symlinks=true
core.autocrlf=true
core.fscache=true
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
help.format=html
diff.astextplain.textconv=astextplain
rebase.autosquash=true
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
http.sslbackend=openssl
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
credential.helper=manager
core.editor='C:\Program Files (x86)\Notepad++\notepad++.exe' -multiInst - notabbar -nosession -noPlugin
core.excludesfile=C:\GIT\gitignore\VisualStudio.gitignore
core.editor=notepad
core.fscache=true
core.preloadindex=true
gui.fontdiff=-family Consolas -size 10 -weight normal -slant roman - underline 0 -overstrike 0
gui.recentrepo=C:/GIT/polarisv4
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
user.name=xxxxx
user.email=xxxxxx
difftool.sourcetree.cmd='C:/Program Files/TortoiseGit/bin/TortoiseGitMerge.exe' "$LOCAL" "$REMOTE"
mergetool.sourcetree.cmd='C:/Program Files/TortoiseGit/bin/TortoiseGitMerge.exe' -base:"$BASE" -mine:"$LOCAL" - theirs:"$REMOTE" -merged:"$MERGED"
mergetool.sourcetree.trustexitcode=true
alias.co=checkout
alias.br=branch
alias.st=status
winupdater.recentlyseenversion=2.15.1.windows.2
credential.helper=manager
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
As DaveW said the problem comes from the core.fscache=true setting. This is a Windows only setting that enable a file system cache in order to mitigate slowness of some Windows file system operations. Here is the description extracted from the commit message Win32: add a cache below mingw's lstat and dirent implementations:
Checking the work tree status is quite slow on Windows, due to slow
lstat emulation (git calls lstat once for each file in the index).
Windows operating system APIs seem to be much better at scanning the
status of entire directories than checking single files.
Add an lstat implementation that uses a cache for lstat data. Cache
misses read the entire parent directory and add it to the cache.
Subsequent lstat calls for the same directory are served directly from
the cache.
Also implement opendir / readdir / closedir so that they create and
use directory listings in the cache.
The cache doesn't track file system changes and doesn't plug into any
modifying file APIs, so it has to be explicitly enabled for git
functions that don't modify the working copy.
The last sentence of this commit message gives an indication of the cause of the OP problem.
At Ortomala Lokni's suggestion, I removed all global git config files 1.
The problem went away. I reinstated each file until the problem returned and then fiddled with settings that seemed like reasonable candidates.
The culprit was fscache - setting true causes the problem. I have no idea why as the same setting works fine on other PCs.
Thanks everyone for your help!

Git untracked/unstaged files right after clone

I make clone of a git repository, and right after it I get untracked and unstaged (modified/deleted) files in git status. Then I set fileMode=false for Mac, and several files go away from unstaged. But I cannot understand what to do with the others. I've tried a bunch of things from stackoverflow and other places, but nothing helps.
So my question is why I get all these untracked / unstaged files right after cloning the repo, and how to fix it. I use Mac for development, but I've tried to clone repo in Windows to see if it's the same or not. It's even funnier: it says some unstaged files deleted.
After different modifications of git config, the command git config -l looks like this:
Mac:
filter.lfs.clean=git-lfs clean %f
filter.lfs.smudge=git-lfs smudge %f
filter.lfs.required=true
user.email=...hidden...
user.name=...hidden...
core.autocrlf=true
core.precomposeunicode=true
core.filemode=false
core.trustctime=false
alias.gr=log --graph --full-history --all --color --decorate
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
remote.origin.url=https://bitbucket.org/...hidden...
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.demo.remote=origin
branch.demo.merge=refs/heads/demo
Win:
core.symlinks=false
core.autocrlf=true
core.fscache=true
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
help.format=html
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
diff.astextplain.textconv=astextplain
rebase.autosquash=true
credential.helper=manager
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
remote.origin.url=https://bitbucket.org/...hidden...
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.demo.remote=origin
branch.demo.merge=refs/heads/demo
My git status looks like this:
Mac:
Win:
How can it be solved?
OK, after some time of working on the problem I've found 2 solutions in this post (which is also mentioned by Christoph), it was filemode=false and lowercase twins. But untracked files remained. Then I understood that these untracked files have UTF8 characters in their filenames, and somewhere these characters were misunderstood by filesystem and/or git. I looked at these files and found that they are not actual anymore, so I just deleted them and commited this deletion.

Windows-specific Git configuration settings; where are they set?

I've read the Git documentation and Where do the settings in my Git configuration come from? and yet I still can't make sense of some of my settings.
I'm on Git 2.5.3 on Windows 10. Here's the output of git config -l:
λ git config -l
core.symlinks=false
core.autocrlf=true
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
pack.packsizelimit=2g
help.format=html
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
sendemail.smtpserver=/bin/msmtp.exe
diff.astextplain.textconv=astextplain
rebase.autosquash=true
user.name=Ben Collins
user.email=#redacted#
alias.sm=submodule
alias.br=branch
alias.co=checkout
alias.st=status
alias.rebuild=!git rm --cached -r . && git reset --hard
core.excludesfile=C:\Users\Benjamin\Documents\gitignore_global.txt
core.editor=c:/Users/Benjamin/AppData/Local/atom/bin/atom.cmd
core.attributesfile=C:\Users\Benjamin\.gitattributes
push.default=simple
merge.tool=p4merge
mergetool.p4merge.cmd=p4merge.exe "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
mergetool.p4merge.path=C:/Program Files/Perforce/p4merge.exe
gui.encoding=utf-8
diff.guitool=p4merge
difftool.p4merge.path=C:/Program Files/Perforce/p4merge.exe
difftool.p4merge.cmd=p4merge.exe "$LOCAL" "$REMOTE"
mergetool.keepbackup=false
rerere.enabled=true
credential.helper=!'C:\Users\Benjamin\AppData\Roaming\GitCredStore\git-credential-winstore.exe'
filter.lfs.clean=git lfs clean %f
filter.lfs.smudge=git lfs smudge %f
filter.lfs.required=true
color.diff.whitespace=red reverse
What's bothersome is that the first twelve settings I cannot find anywhere.
C:\Program Files\Git
λ git config --system --list
fatal: unable to read config file 'C:\Program Files\Git\mingw64/etc/gitconfig': No such file or directory
C:\Program Files\Git
λ git config --global --list
user.name=Ben Collins
user.email=#redacted#
alias.sm=submodule
alias.br=branch
alias.co=checkout
alias.st=status
alias.rebuild=!git rm --cached -r . && git reset --hard
core.excludesfile=C:\Users\Benjamin\Documents\gitignore_global.txt
core.editor=c:/Users/Benjamin/AppData/Local/atom/bin/atom.cmd
core.attributesfile=C:\Users\Benjamin\.gitattributes
push.default=simple
merge.tool=p4merge
mergetool.p4merge.cmd=p4merge.exe "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
mergetool.p4merge.path=C:/Program Files/Perforce/p4merge.exe
gui.encoding=utf-8
diff.guitool=p4merge
difftool.p4merge.path=C:/Program Files/Perforce/p4merge.exe
difftool.p4merge.cmd=p4merge.exe "$LOCAL" "$REMOTE"
mergetool.keepbackup=false
rerere.enabled=true
credential.helper=!'C:\Users\Benjamin\AppData\Roaming\GitCredStore\git-credential-winstore.exe'
filter.lfs.clean=git lfs clean %f
filter.lfs.smudge=git lfs smudge %f
filter.lfs.required=true
color.diff.whitespace=red reverse
Also, when I try to unset one of the first twelve settings, it has no effect:
C:\Users\Benjamin\Projects\blah [master +0 ~1 -0]
λ git config --unset core.autocrlf
C:\Users\Benjamin\Projects\blah [master +0 ~1 -0]
λ git config core.autocrlf
true
C:\Users\Benjamin\Projects\Saddleback\cm-core [master +0 ~1 -0]
λ git config --unset-all core.autocrlf
C:\Users\Benjamin\Projects\Saddleback\cm-core [master +0 ~1 -0]
λ git config core.autocrlf
true
Are these first twelve settings hardcoded or platform-specific somehow? How do I get control of them?
As this commit explains, they've added another config location only for Windows, which is applied even before the --system:
The file /etc/gitconfig can be used to store a system-wide default
configuration. On Windows, configuration can also be stored in
C:\ProgramData\Git\config; This file will be used also by
libgit2-based software.
...
On Windows, as there is no central /etc/ directory, there is yet
another config file, intended to contain settings for all
Git-related software running on the machine. Consequently, this config
file takes an even lower precedence than the $(prefix)/etc/gitconfig
file.
So I believe you can find those mystery settings in C:\ProgramData\Git\config.
From that commit I can see that git config --system --list should've shown you those settings, but it seems that the absence of C:\Program Files\Git\mingw64/etc/gitconfig file aborted the operation, which is probably a bug.
In my version of git there is a --show-origin switch on the list command which gives away where the setting was applied from. I agree that it's confusing that there is no provided switch to access the windows configuration location inside ProgramData.
C:\Users\karlb>git --version
git version 2.11.0.windows.3
C:\Users\karlb>git config --list --show-origin
file:"C:\\ProgramData/Git/config" core.symlinks=false
file:"C:\\ProgramData/Git/config" core.autocrlf=true
file:"C:\\ProgramData/Git/config" core.fscache=true
file:"C:\\ProgramData/Git/config" color.diff=auto
file:"C:\\ProgramData/Git/config" color.status=auto
file:"C:\\ProgramData/Git/config" color.branch=auto
file:"C:\\ProgramData/Git/config" color.interactive=true
file:"C:\\ProgramData/Git/config" help.format=html
file:"C:\\ProgramData/Git/config" http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
file:"C:\\ProgramData/Git/config" diff.astextplain.textconv=astextplain
file:"C:\\ProgramData/Git/config" rebase.autosquash=true
file:"C:\\Program Files\\Git\\mingw64/etc/gitconfig" credential.helper=manager
file:"C:\\Program Files\\Git\\mingw64/etc/gitconfig" difftool.usebuiltin=true
file:"C:\\Program Files\\Git\\mingw64/etc/gitconfig" alias.lol=log --oneline --graph
file:"C:\\Program Files\\Git\\mingw64/etc/gitconfig" alias.last=log -1 HEAD
file:C:/Users/karlb/.gitconfig user.email=karl.horton#yahoo.com
file:C:/Users/karlb/.gitconfig user.name=Karl Horton
TIL a caveat concerning Git for Widows. I have git version 2.17.1.windows.2.
I tried to set a global core.attributesfile to override the line-ending attributes for *.sh files (I use WSL, and the present version becomes very unhappy when it tries to run shell scripts with DOS (CRLF) line endings. For Git on the Linux side, the following lines in ~\.gitattributes solve the problem:
*.sln text eol=crlf
*.bat text eol=crlf
*.sh text eol=cr
But using Git from Windows side (e.g. via Sourcetree GUI), for some repositories, I was still getting CRLF in *.sh files.
I found that in these repositories, core.autocrlf=true. Setting it to input solves the problem, and Git respects the global gitattributes now.

Resources