SysTutorials

Resolving Git Push 403 Forbidden: Authentication and Permissions

A 403 Forbidden error when running git push means your credentials aren’t valid or you lack permission to access the repository. This is one of the most common Git frustrations, but it’s usually fixable once you understand what’s actually happening.

Why 403 Errors Happen

Diagnose the Problem

Start by checking your current remote configuration:

git remote -v

This shows which URL your local repository uses. HTTPS output looks like:

origin  https://github.com/username/repo.git (fetch)
origin  https://github.com/username/repo.git (push)

SSH output looks like:

origin  git@github.com:username/repo.git (fetch)
origin  git@github.com:username/repo.git (push)

Next, check which authentication method Git is actually using:

# For SSH
ssh -T git@github.com

# For HTTPS, attempt a push and note the error
git push

For SSH, you should see: Hi username! You've successfully authenticated...

SSH avoids token expiration headaches and is more secure than HTTPS with tokens.

First, verify your SSH setup works:

ssh -T git@github.com

If you get Permission denied (publickey), you need to generate or add an SSH key. Generate a new key if you don’t have one:

ssh-keygen -t ed25519 -C "your_email@example.com"

Press Enter to accept the default location (~/.ssh/id_ed25519), then add a passphrase if desired.

Add the public key to GitHub:

cat ~/.ssh/id_ed25519.pub

Copy the output and paste it into GitHub Settings → SSH and GPG keys → New SSH key.

Ensure your SSH key is loaded in the agent:

ssh-add ~/.ssh/id_ed25519

Now update your remote URL:

git remote set-url origin git@github.com:username/repo.git

Verify the change:

git remote -v

Try pushing:

git push origin main

Solution 2: Use HTTPS with a Personal Access Token

If you need to use HTTPS (common in CI/CD pipelines), use a Personal Access Token instead of your GitHub password.

Generate a token on GitHub:

  1. Go to Settings → Developer settings → Personal access tokens → Tokens (classic)
  2. Click “Generate new token”
  3. Give it a descriptive name
  4. Select the repo scope for full repository access (or public_repo if the repo is public)
  5. Set an expiration date (90 days or less is recommended)
  6. Click “Generate token” and copy it immediately — you won’t see it again

Update your remote if needed:

git remote set-url origin https://github.com/username/repo.git

To avoid entering credentials every push, configure a credential helper:

On Linux (using in-memory cache):

git config --global credential.helper cache
git config --global credential.helper 'cache --timeout=3600'

On macOS (using Keychain):

git config --global credential.helper osxkeychain

On Windows (using Credential Manager):

git config --global credential.helper manager

On your next push, you’ll be prompted for username and password. Use your GitHub username and paste the PAT as the password.

Solution 3: Clear Cached Credentials

If you have old or invalid credentials cached, clear them:

On Linux/macOS:

rm ~/.git-credentials

Using Git’s credential helper:

git credential reject
# Then type:
# host=github.com
# Press Enter twice

On Windows, use Credential Manager GUI:

Go to Control Panel → Credential Manager → Windows Credentials and remove GitHub entries.

Verify Permissions and Repository Status

If you own the repository but still get 403:

If you’re pushing to someone else’s repository, you need:

Test Your Fix

After making changes, attempt to push:

git push origin main

Replace main with your actual branch name if different. A successful push shows:

Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 456 bytes | 456.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), done.
To github.com:username/repo.git
   abc1234..def5678  main -> main

Troubleshooting Checklist

SSH is the long-term solution if you’re working regularly with Git. It’s more secure, doesn’t require token management, and works the same way across all platforms once configured.

← All posts