2

I have 2 GitHub repos, let's call them GH1 and GH2, and 2 corresponding local repos, let's call them LR1 and LR2 that have them as remotes. For clarity, here is the local repo to remote repo mapping:
LR1 ---> GH1
LR2 ---> GH2

I manually upload (and commit) the same file, let's call it A.jpg, to both GitHub repos using the GitHub web UI. I get different results when I try to merge from the remotes back down to my local repos.

I use git on the command line for the purposes of this problem.

One of local repos (LR1) behaves as I would expect: git fetch gets the change from the remote but doesn't merge it. git merge merges A.jpg and fast-forwards the local repo. git status shows that there is "nothing to commit, working directory clean"

The other one (LR2) behaves differently than I would expect: git fetch gets the change from the remote but doesn't merge it. git merge merges A.jpg and fast-forwards the local repo. git status shows that A.jpg is modified and is an uncommitted change.

git pull behaves the same way, with respect to the 2 local repos, but for the purposes of breaking this problem down, I thought I would explicitly call out the 2 commands (git fetch and git merge) that do the same thing as a pull.

I assume that I have the 2 local git repos configured differently and that is causing the issue. What would cause this behaviour?

Kevin
  • 177
  • 2
  • 16
  • Check to see if local repo 2 has CRLF-style line ending modification enabled and is treating `A.jpg` as a text file. If so, make sure it treats `A.jpg` as binary, or does not have CRLF adjustment turned on. – torek Sep 27 '20 at 02:49
  • @Kevin What does `git check-attr --all -- A.jpg` returns in both repository? – VonC Sep 27 '20 at 12:55
  • @torek I tried the same thing with a JS file (a text file) and I get the same result. So, it doesn't look like it's CRLF/binary/text file related. – Kevin Sep 27 '20 at 12:59
  • @VonC running that command in both repositories returns nothing. – Kevin Sep 27 '20 at 13:06
  • Do you have two files whose names differ only in case? Are you on macOS or Windows, or some other OS (which one)? What version of Git are you using? – bk2204 Sep 27 '20 at 18:04
  • Another possibility: if you set up your repository in an auto-sync-ed directory (e.g., under Dropbox), that can corrupt it. Git is picky about where it lives :-) – torek Sep 27 '20 at 20:24
  • @bk2204 Linux. git version 2.7.4 – Kevin Sep 27 '20 at 23:03
  • @torek Thanks, but the folders where the local repos are located aren't anywhere special...one is under my home folder (local disk) and the other is in a different location (mounted SMB share) ... definitely not anything like Dropbox or auto-sync going on. Should I make sure they're both located on the same disk/mount and then compare behaviour again? Or is that too far out there? – Kevin Sep 27 '20 at 23:15
  • 1
    An SMB-share *shouldn't* cause problems, but it's worth a try to eliminate it as a possibility. – torek Sep 28 '20 at 01:26
  • @torek Well, I couldn't eliminate it as a possibility. Instead, I proved that SMB vs. local disk caused the behaviour! The only difference I can see between the files is the permissions: `-rw-rw-r-- 1 kevin kevin 190370 Sep 27 21:51 -2020-09-31.pdf` vs. `-rwxr-xr-x 1 kevin kevin 190370 Sep 27 21:55 -2020-09-31.pdf`. So, I assume that I have to fix how I'm mounting my SMB share because that's where it's defined how permissions are assigned when creating a file, right? Or is this still something I can configure/fix with git? – Kevin Sep 28 '20 at 04:02
  • 1
    Aha! It's your SMB server trying to compensate for Windows execute bit permissions (or lack thereof). It's a bit odd since Linux has proper execute permissions and I *think* there's a translation method that works. See https://unix.stackexchange.com/questions/103415/why-are-files-in-a-smbfs-mounted-share-created-with-executable-bit-set for some speculation. – torek Sep 28 '20 at 04:11
  • 1
    If you can't get the SMB server and Linux system to cooperate, you can have Git explicitly ignore execute permission. In fact, if the server always keeps the `x` bit set, `git init` or `git clone` should have done this already, suggesting that the server *can* support modes 644 and 755 both, and is just creating files incorrectly (which might be mostly-fixable on the Linux mount end by having the Linux system chmod after create). In any case the Git setting is `core.filemode` (can be spelled `core.fileMode`). – torek Sep 28 '20 at 04:13

1 Answers1

3

I'll share my understanding of the problem and how I resolved this, thanks to the helpful comments on this post.

The problem has everything to do with the SMB mount, file permissions, and git configuration. The problem is that when I use git to sync from the remote to my local repo and a new file needs to be created by git in my local repo, git is creating a new file using its default setting for permissions (644) and the SMB mount, under which the local repo existed, has no setting configured for file mode so it was using its default (755). The end result was that git thought it was creating a file with 644 permissions but as soon it got created it assumed 755 permissions because that's what the mount forces for new files...and so git thought that the file it just created had changed and deemed it as an uncommitted locally changed file. This was resolved by a few changes:

  • Changed the SMB mount in /etc/fstab to include the file mode (file_mode=0644) that matches what git wants
  • Once I did this and unmounted/remounted it, all of the files in my local repo now show as uncommitted local changes because the permission (644) is different than what my local repo is aware of and my git settings are sensitive to that. I verified it by checking the git settings

git config --get core.fileMode

  • This was resolved by changing the git configuration for the repository. In the .git folder in the local repo root, I edited the config file so that filemode = false.
  • Once I did this, git status shows that there are no uncommitted local changes.

This git documentation explains well how this could happen, which is very close to what happened to me (i.e. cloned remote repo to local repo on local disk before it was on SMB mount and then eventually moved the local repo to an SMB mount)

Now, new files added to the GitHub repo and then pulled down to the local repo no longer show up as locally uncommited changes. Rather, they are merged properly and transparently.

Kevin
  • 177
  • 2
  • 16