GitResolving Permission Issues

Resolving Git Permission Issues

Permission errors in Git come from two different layers: network authentication (SSH keys, HTTPS credentials) and filesystem ownership (.git directory, shared repositories). This page covers every common permission scenario with exact error messages and step-by-step fixes.

1. Permission denied (publickey) — SSH authentication

Error

Bash
git push origin main
# git@github.com: Permission denied (publickey).
# fatal: Could not read from remote repository.

Your SSH key is either not generated, not added to the SSH agent, or not registered with the hosting platform.

Full SSH setup walkthrough

Bash
# Step 1: Check if you have an SSH key
ls ~/.ssh/
# id_ed25519  id_ed25519.pub   ← good, key exists
# (empty)                      ← need to generate one

# Step 2: Generate an SSH key if needed
ssh-keygen -t ed25519 -C "your@email.com"
# Generating public/private ed25519 key pair.
# Enter file in which to save the key (/home/user/.ssh/id_ed25519): [Enter]
# Enter passphrase: [your passphrase or leave blank]

# Step 3: Start the SSH agent
eval "$(ssh-agent -s)"
# Agent pid 12345

# Step 4: Add the key to the agent
ssh-add ~/.ssh/id_ed25519

# Step 5: Copy the public key to your clipboard
cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAAC3NzaC1... your@email.com

# Step 6: Add the key to GitHub/GitLab
# GitHub: Settings → SSH and GPG keys → New SSH key
# GitLab: User Settings → SSH Keys

# Step 7: Test the connection
ssh -T git@github.com
# Hi username! You've successfully authenticated, but GitHub does
# not provide shell access.
Persistent SSH agent on macOS
Add this to `~/.ssh/config` to auto-load your key on macOS without running `ssh-add` every session:

~/.ssh/config

Text
Host github.com
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519
2. fatal: Authentication failed — HTTPS credentials

Error

Bash
git push origin main
# remote: Invalid username or password.
# fatal: Authentication failed for 'https://github.com/user/repo.git'

GitHub removed password authentication in 2021. You must use a Personal Access Token (PAT) instead of your account password for HTTPS.

Fix: use a Personal Access Token

Bash
# Step 1: Create a PAT at GitHub: Settings → Developer settings → Personal access tokens

# Step 2: Update the credential stored in the OS keychain
git credential reject
# (then fill in: protocol=https, host=github.com, [Enter][Enter])

# Or clear stored credentials on macOS
git credential-osxkeychain erase
# protocol=https
# host=github.com
# [press Enter twice]

# Step 3: Push — Git will prompt for username + password
git push origin main
# Username: your-github-username
# Password: ghp_your_personal_access_token  ← paste the PAT here

Store credentials so you are not prompted every time

Bash
# macOS (uses Keychain)
git config --global credential.helper osxkeychain

# Windows (uses Windows Credential Manager)
git config --global credential.helper manager

# Linux — cache for 1 hour
git config --global credential.helper 'cache --timeout=3600'

# Linux — store in plaintext (less secure)
git config --global credential.helper store
3. error: insufficient permission for adding an object

Error

Bash
git push
# error: insufficient permission for adding an object to repository database .git/objects
# fatal: failed to write object
# error: unpack failed: unpack-objects abnormal exit

The .git/objects directory on the server is owned by a different user than the one running Git. This typically happens on shared servers or after running Git commands as root.

Fix on a bare server repo

Bash
# Check ownership
ls -la /srv/git/repo.git/objects/
# drwx------ root root .  ← wrong owner

# Fix ownership (replace 'git' with your deploy user)
sudo chown -R git:git /srv/git/repo.git

# Fix permissions on the objects directory
sudo chmod -R 770 /srv/git/repo.git
sudo find /srv/git/repo.git/objects -type f -exec chmod 440 {} ;

# For shared repositories, set core.sharedRepository
cd /srv/git/repo.git
git config core.sharedRepository group
4. fatal: dubious ownership in repository (Git 2.36+)

Error

Bash
git status
# fatal: detected dubious ownership in repository at '/workspace/project'
# To add an exception for this directory, call:
#
#         git config --global --add safe.directory /workspace/project

Git 2.36 added a security check that refuses to run if the repository directory is owned by a different user than the one running Git. This is common in Docker containers and CI environments.

Fix: add directory to safe.directory

Bash
# Allow this specific directory
git config --global --add safe.directory /workspace/project

# Allow all directories (for CI containers — understand the security trade-off)
git config --global --add safe.directory '*'

# In a Dockerfile or CI config, set the env variable instead:
# GIT_CONFIG_GLOBAL=/dev/null  (or set safe.directory in config)
Warning
`safe.directory '*'` disables the ownership check for all repositories. Only use this in isolated CI containers where all code is trusted. Do not use it on a shared developer machine.
5. Linux: wrong .git folder owner

Symptoms

Bash
ls -la .git/
# drwxr-xr-x  root root objects/   ← created when someone ran git as root
# drwxr-xr-x  jane jane  refs/

Fix: restore correct ownership

Bash
# Replace 'jane' with your username
sudo chown -R jane:jane .git/

# Verify
ls -la .git/
# drwxr-xr-x  jane jane  objects/
# drwxr-xr-x  jane jane  refs/
6. Windows: symlink permission errors

Error on Windows

Bash
git checkout feature-x
# error: unable to create file docs/link.txt: Invalid argument
# or
# warning: unable to create symlink 'src/shared' (Operation not permitted)

On Windows, creating symlinks requires either Developer Mode (Windows 10+) or administrator privileges.

Fix

Bash
# Option A: Enable Developer Mode in Windows Settings
# Settings → Update & Security → For Developers → Developer Mode → On

# Option B: Disable core.symlinks in Git (treats symlinks as plain text files)
git config --global core.symlinks false

# Option C: Run Git Bash as Administrator for the operation
7. Firewall blocking SSH port 22 — use SSH over port 443

Symptom

Bash
ssh -T git@github.com
# ssh: connect to host github.com port 22: Connection timed out

Corporate firewalls often block outbound TCP on port 22. GitHub and GitLab both support SSH on port 443 as an alternative.

Test SSH on port 443

Bash
ssh -T -p 443 git@ssh.github.com
# Hi username! You've successfully authenticated...

~/.ssh/config — use port 443 for GitHub automatically

Text
Host github.com
  Hostname ssh.github.com
  Port 443
  User git
  IdentityFile ~/.ssh/id_ed25519

~/.ssh/config — GitLab on port 443

Text
Host gitlab.com
  Hostname altssh.gitlab.com
  Port 443
  User git
  IdentityFile ~/.ssh/id_ed25519
Tip
After updating `~/.ssh/config`, test with `ssh -T git@github.com` — it will now automatically use port 443.
Quick reference table

Error

Layer

Fix command

Permission denied (publickey)

SSH auth

ssh-add ~/.ssh/id_ed25519

Authentication failed

HTTPS auth

Use Personal Access Token as password

insufficient permission for adding object

Filesystem

sudo chown -R user:user .git/

dubious ownership

Security (Git 2.36+)

git config --global --add safe.directory /path

Wrong .git owner on Linux

Filesystem

sudo chown -R user:user .git/

Symlink error on Windows

OS permissions

Enable Developer Mode or core.symlinks false

Port 22 blocked

Network/firewall

SSH over port 443 via ~/.ssh/config

Diagnosing unknown permission errors
  • Run ssh -vT git@github.com for verbose SSH debugging output.

  • Check git config --list to see all active configuration.

  • Run ls -la .git/ to inspect object directory ownership.

  • Try GIT_TRACE=1 git push for a detailed trace of every Git operation.

  • On macOS, check Keychain Access for stale credentials if HTTPS keeps failing.