Troubleshooting of GIT
Troubleshooting of GIT
Restoring deleted files in Git
Restoring deleted files in Git
SSH Authentication Failed: Permission denied (publickey)
Error Message
After running the command:
git clone [email protected]:your-org/your-repo.git /opt/your-app
you may see the following error:
Cloning into '/opt/your-app'... [email protected]: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
A similar error may also occur when running:
git pull
or:
sudo git pull
Cause
This error occurs when Git cannot authenticate with GitHub over SSH.
Common causes include:
- The SSH key does not exist on the server.
- The SSH key has not been added to GitHub.
- The SSH key is added to the wrong GitHub account or the wrong repository.
- The repository is private and the key does not have access.
- The server has multiple SSH keys, but Git is using the wrong one.
- The key is a GitHub Deploy Key that belongs to another repository.
- `sudo git clone` or `sudo git pull` is being used, causing Git to use the `root` user's SSH key instead of the deploy user's SSH key.
For example, if you run:
ssh -T [email protected]
and see:
Hi other-org/other-repo! You've successfully authenticated, but GitHub does not provide shell access.
it means the current SSH key is valid, but it is linked to another repository's Deploy Key. In that case, GitHub may return:
ERROR: Repository not found.
even if the target repository URL is correct.
Recommended Solution — Use a dedicated SSH alias for the project
This is the safest approach when the server has multiple GitHub Deploy Keys.
Assume:
Deploy user: your-user App path: /opt/your-app Private key: /home/your-user/.ssh/id_ed25519_your_app Public key: /home/your-user/.ssh/id_ed25519_your_app.pub Repository: [email protected]:your-org/your-repo.git
Step 1 — Check the key exists
ls -l ~/.ssh/id_ed25519_your_app*
Expected result:
/home/your-user/.ssh/id_ed25519_your_app /home/your-user/.ssh/id_ed25519_your_app.pub
If the key does not exist, create one:
ssh-keygen -t ed25519 -C "your-app-deploy-key" -f ~/.ssh/id_ed25519_your_app
Step 2 — Add the public key to GitHub
Print the public key:
cat ~/.ssh/id_ed25519_your_app.pub
Add it to the target repository:
GitHub Repository → Settings → Deploy keys → Add deploy key
If the server only needs to clone or pull the repository, do not enable write access.
Step 3 — Configure SSH alias
Edit the SSH config file:
nano ~/.ssh/config
Add:
Host github-your-app HostName github.com User git IdentityFile ~/.ssh/id_ed25519_your_app IdentitiesOnly yes
Fix SSH file permissions:
chmod 700 ~/.ssh chmod 600 ~/.ssh/config ~/.ssh/id_ed25519_your_app chmod 644 ~/.ssh/id_ed25519_your_app.pub
Explanation:
~/.sshshould be accessible only by the current user~/.ssh/config/should be readable/writable only by the current user~/.ssh/id_ed25519_your_appprivate key should be readable only by the current user~/.ssh/id_ed25519_your_app.pubpublic key can be readable by others
Step 4 — Test the SSH alias
Run:
ssh -T github-your-app
Expected result:
Hi your-org/your-repo! You've successfully authenticated, but GitHub does not provide shell access.
The message:
GitHub does not provide shell access.
is expected. It means SSH authentication works, but GitHub does not allow interactive shell login.
If the result shows another repository, for example:
Hi other-org/other-repo! You've successfully authenticated, but GitHub does not provide shell access.
then the alias is not using the intended key, or the key was added to the wrong repository.
Step 5 — Clone using the SSH alias
Instead of:
git clone [email protected]:your-org/your-repo.git /opt/your-app
use:
git clone git@github-your-app:your-org/your-repo.git /opt/your-app
If `/opt/your-app` requires root permission to create, prefer creating the directory first and assigning ownership to the deploy user:
sudo mkdir -p /opt/your-app sudo chown -R your-user:your-user /opt/your-app git clone git@github-your-app:your-org/your-repo.git /opt/your-app
This avoids using `sudo git clone`.
Step 6 — If the repository already exists, update the remote URL
Check the current remote:
cd /opt/your-app git remote -v
If it uses the default GitHub host:
origin [email protected]:your-org/your-repo.git (fetch) origin [email protected]:your-org/your-repo.git (push)
change it to use the SSH alias:
git remote set-url origin git@github-your-app:your-org/your-repo.git
Verify:
git remote -v
Expected result:
origin git@github-your-app:your-org/your-repo.git (fetch) origin git@github-your-app:your-org/your-repo.git (push)
Then run:
git pull
Avoid using sudo with Git
Avoid:
sudo git clone [email protected]:your-org/your-repo.git /opt/your-app sudo git pull
Because `sudo` runs Git as `root`, Git may use root's SSH keys instead of the deploy user's SSH keys.
If the app directory is owned by `root`, fix ownership instead:
sudo chown -R your-user:your-user /opt/your-app
Then run Git commands as the deploy user:
cd /opt/your-app git pull
Related Issue: dubious ownership
If Git shows:
fatal: detected dubious ownership in repository at '/opt/your-app'
it means the current user and the repository owner do not match.
Check:
ls -ld /opt/your-app whoami
If the app should be maintained by the deploy user, fix ownership:
sudo chown -R your-user:your-user /opt/your-app
Alternatively, mark the directory as safe:
git config --global --add safe.directory /opt/your-app
For deployment directories, fixing ownership is usually cleaner if the deploy user is expected to run `git pull`.
Alternative Solution — Pass the SSH key inline
You can also override the SSH command directly.
First, test the key:
ssh -T -i /path/to/.ssh/your_key_name -o IdentitiesOnly=yes [email protected]
Expected result:
Hi your-org/your-repo! You've successfully authenticated, but GitHub does not provide shell access.
Then clone:
GIT_SSH_COMMAND='ssh -i /path/to/.ssh/your_key_name -o IdentitiesOnly=yes' \ git clone [email protected]:your-org/your-repo.git /opt/your-app
If you need to run this with `sudo`, preserve the environment explicitly:
sudo GIT_SSH_COMMAND='ssh -i /path/to/.ssh/your_key_name -o IdentitiesOnly=yes' \ git clone [email protected]:your-org/your-repo.git /opt/your-app
However, this is usually less clean than using an SSH alias, especially for long-term maintenance.
Notice
-o IdentitiesOnly=yes
forces SSH to use only the specified key and prevents SSH from trying other keys loaded in the agent. This is important on servers with multiple Deploy Keys.
Summary
Recommended long-term setup:
# 1. Create or confirm a dedicated deploy key ls ~/.ssh/id_ed25519_your_app* # 2. Add the public key to the target GitHub repository Deploy Keys cat ~/.ssh/id_ed25519_your_app.pub # 3. Configure SSH alias nano ~/.ssh/config # 4. Test alias ssh -T github-your-app # 5. Clone or update remote using alias git clone git@github-your-app:your-org/your-repo.git /opt/your-app # or, for an existing repo cd /opt/your-app git remote set-url origin git@github-your-app:your-org/your-repo.git git pull
The key lesson is: when multiple Deploy Keys exist on the same server, avoid relying on `[email protected]`. Use a project-specific SSH alias such as:
git@github-your-app:your-org/your-repo.git
so Git always uses the correct SSH key.
Git Submodule Pull Failed: unable to create file — File exists
Error Message
After pulling in GitHub Desktop, met the error message
Fetching submodule lib error: unable to create file feeds/example.php: File exists Updating xxxxxxxx..xxxxxxxx
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:
git submodule update --init --recursive --force
If it still fails, manually remove the conflicting file and retry:
rm lib/feeds/example.php git submodule update --init --recursive
Enter the submodule directory and verify the status is clean:
cd lib git status
The expected output should be:
HEAD detached from xxxxxxxx nothing to commit, working tree clean
`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.
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 git submodule foreach git checkout . to revert all modifications inside every submodule.