Troubleshooting of GIT: Difference between revisions

Jump to navigation Jump to search
m
Line 1: Line 1:


== Troubleshooting of GIT ==
== Troubleshooting of GIT ==
=== Git Push Failed: Invalid username or token (GitHub No Longer Supports Password Authentication) ===
'''Problem'''
Running <code>git push</code> produces the following error:
<pre>
remote: Invalid username or token. Password authentication is not supported for Git operations.
fatal: Authentication failed for 'https://github.com/team_name/repo_name/'
In a case you entered incorrect password, please
update it in Keychain Access application.
</pre>
'''Diagnosis'''
First check the current login status of the GitHub CLI:
<pre>
gh auth status
</pre>
If the token has expired, a message similar to the following will appear:
<pre>
github.com
  X Failed to log in to github.com account UserName (keyring)
* Active account: true
* The token in keyring is invalid.
* To re-authenticate, run: gh auth login -h github.com
* To forget about this account, run: gh auth logout -h github.com -u UserName
</pre>
You can also directly query the GitHub credentials stored in the macOS Keychain:
<pre>
security find-internet-password -s github.com
</pre>
'''Cause'''
This error is typically caused by one of the following:
* An old GitHub account password (rather than a token) is stored in the macOS Keychain, and Git's attempt to authenticate with that password fails.
* The Personal Access Token in the <code>gh</code> keyring has expired, been revoked, or had its permissions changed.
* A token or SSH key was never set up, so Git is still falling back to the legacy password authentication flow.
'''Solution'''
'''Re-authenticate the GitHub CLI'''
<pre>
gh auth login -h github.com
</pre>
Select the following options in order:
* What is your preferred protocol for Git operations on this host? → <code>HTTPS</code> (matches the existing remote protocol)
* How would you like to authenticate GitHub CLI? → <code>Login with a web browser</code>
A one-time code will be displayed. Copy it and press Enter; a browser window will open the GitHub device authorization page to complete the login:
<pre>
! First copy your one-time code: XXXX-XXXX
Press Enter to open https://github.com/login/device in your browser...
✓ Authentication complete.
* gh config set -h github.com git_protocol https
✓ Configured git protocol
✓ Logged in as UserName
</pre>
=== Git Shows Files as Modified After chmod — File Mode Changes ===
'''Problem'''
After running <code>chmod +x</code> or copying the repository between different operating systems or file systems, Git may report files as modified even though their contents have not changed:
<pre>
git status
modified: scripts/deploy.sh
</pre>
Running <code>git diff</code> may show only a file mode change:
<pre>
diff --git a/scripts/deploy.sh b/scripts/deploy.sh
old mode 100644
new mode 100755
</pre>
In Git file modes:
* <code>100644</code> means a regular non-executable file.
* <code>100755</code> means a regular executable file.
Git records the executable bit as part of the tracked file metadata. Therefore, adding or removing executable permission can appear as a modification even when the file contents are identical. Git’s diff format explicitly reports these changes as <code>old mode</code> and <code>new mode</code>.
'''Diagnosis'''
Use the following command to check whether the reported changes are file mode changes only:
<pre>
git diff --summary
</pre>
Example output:
<pre>
mode change 100644 => 100755 scripts/deploy.sh
</pre>
You can also inspect the full diff:
<pre>
git diff
</pre>
If the output contains only <code>old mode</code> and <code>new mode</code>, without added or removed content lines, the change is caused by the executable bit rather than file contents.
Check the current repository setting with: <ref>[https://git-scm.com/docs/git-config?utm_source=chatgpt.com Git - git-config Documentation]</ref>
<pre>
git config --get core.fileMode
</pre>
To see which configuration file defines the value:
<pre>
git config --show-origin --get core.fileMode
</pre>
'''Cause'''
The behavior is controlled by Git’s <code>core.fileMode</code> setting.
When it is set to <code>true</code>, Git checks whether the executable bit in the working tree differs from the mode stored in the Git index. This can create unexpected changes when:
* A file was modified using <code>chmod +x</code> or <code>chmod -x</code>.
* A repository was copied between Linux, macOS, Windows, a network drive, or another file system with different permission behavior.
* An archive, synchronization tool, or shared folder changed executable permissions.
* A container or deployment process rewrote file modes.
Git’s documentation notes that some file systems may not reliably preserve executable-bit information, which is why <code>core.fileMode</code> can be disabled when those mode differences should not be trusted.
'''Solution'''
To ignore executable-permission changes in the current repository, run:
<pre>
git config core.fileMode false
</pre>
This is the recommended scope when the issue affects only one repository. The setting is saved in that repository’s <code>.git/config</code> file.
To apply the setting to all repositories for the current user:
<pre>
git config --global core.fileMode false
</pre>
The global setting is stored in the user-level Git configuration and acts as a fallback unless a repository overrides it.
Verify the effective value:
<pre>
git config --get core.fileMode
</pre>
The expected output is:
<pre>
false
</pre>
Then check the repository again:
<pre>
git status
git diff --summary
</pre>
Permission-only changes should no longer appear as unstaged modifications.
'''Restore File Mode Tracking'''
To restore executable-bit tracking for the current repository:
<pre>
git config core.fileMode true
</pre>
To remove the repository-specific override and return to the global or system default:
<pre>
git config --unset core.fileMode
</pre>
To restore tracking globally:
<pre>
git config --global core.fileMode true
</pre>
'''When the Executable Bit Should Be Committed'''
Do not disable <code>core.fileMode</code> merely to hide a legitimate permission change.
For shell scripts, deployment scripts, Git hooks, command-line tools, and other files that must be executable after checkout, record the executable bit in Git intentionally:
<pre>
chmod +x scripts/deploy.sh
git add scripts/deploy.sh
git commit -m "Mark deploy script as executable"
</pre>
The committed mode change will appear as:
<pre>
mode change 100644 => 100755 scripts/deploy.sh
</pre>
If the local file system cannot apply <code>chmod</code> correctly, update the Git index directly:
<pre>
git update-index --chmod=+x scripts/deploy.sh
git commit -m "Mark deploy script as executable"
</pre>
To remove executable status from the Git index:
<pre>
git update-index --chmod=-x scripts/deploy.sh
</pre>
Git provides index-level support for explicitly overriding a tracked file’s executable bit.
{{exclaim}} Notice: Setting <code>core.fileMode=false</code> does not change the actual operating-system permissions and does not rewrite previously committed file modes. It only tells Git not to treat executable-bit differences in the working tree as modifications. Use a repository-level setting unless the same problem consistently affects all repositories on the machine.
=== Git Submodule Pull Failed: unable to create file — File exists ===
'''Error Message'''
After pulling in GitHub Desktop, met the error message
<pre>
Fetching submodule lib
error: unable to create file feeds/example.php: File exists
Updating xxxxxxxx..xxxxxxxx
</pre>
'''Cause'''
When Git tries to update the submodule to a newer commit, it finds a local untracked file with the same name, blocking the checkout. A mid-pull failure leaves the submodule in an inconsistent state and causes a large number of unexpected unstaged changes to appear in GitHub Desktop.
'''Solution'''
Run the following command in the project root directory to force re-sync the submodule:
<pre>
git submodule update --init --recursive --force
</pre>
If it still fails, manually remove the conflicting file and retry:
<pre>
rm lib/feeds/example.php
git submodule update --init --recursive
</pre>
Enter the submodule directory and verify the status is clean:
<pre>
cd lib
git status
</pre>
The expected output should be:
<pre>
HEAD detached from xxxxxxxx
nothing to commit, working tree clean
</pre>
`nothing to commit, working tree clean` confirms the submodule has been successfully synced — return to GitHub Desktop and continue as normal. `HEAD detached` is the expected state for a submodule and does not require any action.
{{exclaim}} Notice: The large number of unstaged changes appearing in GitHub Desktop after a failed Pull will typically return to normal once the submodule is fixed. If unexpected changes still remain, run <code>git submodule foreach git checkout .</code> to revert all modifications inside every submodule.


=== Restoring deleted files in Git ===
=== Restoring deleted files in Git ===
Line 379: Line 668:


so Git always uses the correct SSH key.
so Git always uses the correct SSH key.
=== Git Push Failed: Invalid username or token (GitHub No Longer Supports Password Authentication) ===
'''Problem'''
Running <code>git push</code> produces the following error:
<pre>
remote: Invalid username or token. Password authentication is not supported for Git operations.
fatal: Authentication failed for 'https://github.com/team_name/repo_name/'
In a case you entered incorrect password, please
update it in Keychain Access application.
</pre>
'''Diagnosis'''
First check the current login status of the GitHub CLI:
<pre>
gh auth status
</pre>
If the token has expired, a message similar to the following will appear:
<pre>
github.com
  X Failed to log in to github.com account UserName (keyring)
* Active account: true
* The token in keyring is invalid.
* To re-authenticate, run: gh auth login -h github.com
* To forget about this account, run: gh auth logout -h github.com -u UserName
</pre>
You can also directly query the GitHub credentials stored in the macOS Keychain:
<pre>
security find-internet-password -s github.com
</pre>
'''Cause'''
This error is typically caused by one of the following:
* An old GitHub account password (rather than a token) is stored in the macOS Keychain, and Git's attempt to authenticate with that password fails.
* The Personal Access Token in the <code>gh</code> keyring has expired, been revoked, or had its permissions changed.
* A token or SSH key was never set up, so Git is still falling back to the legacy password authentication flow.
'''Solution'''
'''Re-authenticate the GitHub CLI'''
<pre>
gh auth login -h github.com
</pre>
Select the following options in order:
* What is your preferred protocol for Git operations on this host? → <code>HTTPS</code> (matches the existing remote protocol)
* How would you like to authenticate GitHub CLI? → <code>Login with a web browser</code>
A one-time code will be displayed. Copy it and press Enter; a browser window will open the GitHub device authorization page to complete the login:
<pre>
! First copy your one-time code: XXXX-XXXX
Press Enter to open https://github.com/login/device in your browser...
✓ Authentication complete.
* gh config set -h github.com git_protocol https
✓ Configured git protocol
✓ Logged in as UserName
</pre>
=== Git Shows Files as Modified After chmod — File Mode Changes ===
'''Problem'''
After running <code>chmod +x</code> or copying the repository between different operating systems or file systems, Git may report files as modified even though their contents have not changed:
<pre>
git status
modified: scripts/deploy.sh
</pre>
Running <code>git diff</code> may show only a file mode change:
<pre>
diff --git a/scripts/deploy.sh b/scripts/deploy.sh
old mode 100644
new mode 100755
</pre>
In Git file modes:
* <code>100644</code> means a regular non-executable file.
* <code>100755</code> means a regular executable file.
Git records the executable bit as part of the tracked file metadata. Therefore, adding or removing executable permission can appear as a modification even when the file contents are identical. Git’s diff format explicitly reports these changes as <code>old mode</code> and <code>new mode</code>.
'''Diagnosis'''
Use the following command to check whether the reported changes are file mode changes only:
<pre>
git diff --summary
</pre>
Example output:
<pre>
mode change 100644 => 100755 scripts/deploy.sh
</pre>
You can also inspect the full diff:
<pre>
git diff
</pre>
If the output contains only <code>old mode</code> and <code>new mode</code>, without added or removed content lines, the change is caused by the executable bit rather than file contents.
Check the current repository setting with: <ref>[https://git-scm.com/docs/git-config?utm_source=chatgpt.com Git - git-config Documentation]</ref>
<pre>
git config --get core.fileMode
</pre>
To see which configuration file defines the value:
<pre>
git config --show-origin --get core.fileMode
</pre>
'''Cause'''
The behavior is controlled by Git’s <code>core.fileMode</code> setting.
When it is set to <code>true</code>, Git checks whether the executable bit in the working tree differs from the mode stored in the Git index. This can create unexpected changes when:
* A file was modified using <code>chmod +x</code> or <code>chmod -x</code>.
* A repository was copied between Linux, macOS, Windows, a network drive, or another file system with different permission behavior.
* An archive, synchronization tool, or shared folder changed executable permissions.
* A container or deployment process rewrote file modes.
Git’s documentation notes that some file systems may not reliably preserve executable-bit information, which is why <code>core.fileMode</code> can be disabled when those mode differences should not be trusted.
'''Solution'''
To ignore executable-permission changes in the current repository, run:
<pre>
git config core.fileMode false
</pre>
This is the recommended scope when the issue affects only one repository. The setting is saved in that repository’s <code>.git/config</code> file.
To apply the setting to all repositories for the current user:
<pre>
git config --global core.fileMode false
</pre>
The global setting is stored in the user-level Git configuration and acts as a fallback unless a repository overrides it.
Verify the effective value:
<pre>
git config --get core.fileMode
</pre>
The expected output is:
<pre>
false
</pre>
Then check the repository again:
<pre>
git status
git diff --summary
</pre>
Permission-only changes should no longer appear as unstaged modifications.
'''Restore File Mode Tracking'''
To restore executable-bit tracking for the current repository:
<pre>
git config core.fileMode true
</pre>
To remove the repository-specific override and return to the global or system default:
<pre>
git config --unset core.fileMode
</pre>
To restore tracking globally:
<pre>
git config --global core.fileMode true
</pre>
'''When the Executable Bit Should Be Committed'''
Do not disable <code>core.fileMode</code> merely to hide a legitimate permission change.
For shell scripts, deployment scripts, Git hooks, command-line tools, and other files that must be executable after checkout, record the executable bit in Git intentionally:
<pre>
chmod +x scripts/deploy.sh
git add scripts/deploy.sh
git commit -m "Mark deploy script as executable"
</pre>
The committed mode change will appear as:
<pre>
mode change 100644 => 100755 scripts/deploy.sh
</pre>
If the local file system cannot apply <code>chmod</code> correctly, update the Git index directly:
<pre>
git update-index --chmod=+x scripts/deploy.sh
git commit -m "Mark deploy script as executable"
</pre>
To remove executable status from the Git index:
<pre>
git update-index --chmod=-x scripts/deploy.sh
</pre>
Git provides index-level support for explicitly overriding a tracked file’s executable bit.
{{exclaim}} Notice: Setting <code>core.fileMode=false</code> does not change the actual operating-system permissions and does not rewrite previously committed file modes. It only tells Git not to treat executable-bit differences in the working tree as modifications. Use a repository-level setting unless the same problem consistently affects all repositories on the machine.
=== Git Submodule Pull Failed: unable to create file — File exists ===
'''Error Message'''
After pulling in GitHub Desktop, met the error message
<pre>
Fetching submodule lib
error: unable to create file feeds/example.php: File exists
Updating xxxxxxxx..xxxxxxxx
</pre>
'''Cause'''
When Git tries to update the submodule to a newer commit, it finds a local untracked file with the same name, blocking the checkout. A mid-pull failure leaves the submodule in an inconsistent state and causes a large number of unexpected unstaged changes to appear in GitHub Desktop.
'''Solution'''
Run the following command in the project root directory to force re-sync the submodule:
<pre>
git submodule update --init --recursive --force
</pre>
If it still fails, manually remove the conflicting file and retry:
<pre>
rm lib/feeds/example.php
git submodule update --init --recursive
</pre>
Enter the submodule directory and verify the status is clean:
<pre>
cd lib
git status
</pre>
The expected output should be:
<pre>
HEAD detached from xxxxxxxx
nothing to commit, working tree clean
</pre>
`nothing to commit, working tree clean` confirms the submodule has been successfully synced — return to GitHub Desktop and continue as normal. `HEAD detached` is the expected state for a submodule and does not require any action.
{{exclaim}} Notice: The large number of unstaged changes appearing in GitHub Desktop after a failed Pull will typically return to normal once the submodule is fixed. If unexpected changes still remain, run <code>git submodule foreach git checkout .</code> to revert all modifications inside every submodule.


== Further Reading ==
== Further Reading ==

Navigation menu