Skip to content

push Git Command Guide

The git push command updates remote refs using local refs, while sending objects necessary to complete the given refs. It publishes local commits to remote repositories and establishes tracking relationships between local and remote branches.

Terminal window
git push [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic]
[-n | --dry-run] [--receive-pack=<git-receive-pack>]
[--repo=<repository>] [-f | --force] [-d | --delete] [--prune]
[-q | --quiet] [-v | --verbose] [-u | --set-upstream]
[-o <string> | --push-option=<string>]
[--[no-]signed|--signed=(true|false|if-asked)]
[--force-with-lease[=<refname>[:<expect>]]] [--force-if-includes]
[--no-verify] [<repository> [<refspec>...]]
OptionDescription
--allPush all branches
--branchesPush all branches (same as —all)
--mirrorMirror all refs
--tagsPush all tags
--follow-tagsPush tags reachable from pushed branches
OptionDescription
-f, --forceForce update remote refs
--force-with-lease[=<refname>[:<expect>]]Force with lease protection
--force-if-includesForce if remote includes specific commit
OptionDescription
-n, --dry-runShow what would be pushed
--atomicUse atomic transactions
-d, --deleteDelete remote refs
--pruneRemove remote branches not in local
-u, --set-upstreamSet upstream tracking
OptionDescription
`—signed=(truefalse
--no-verifySkip pre-push hooks
-o, --push-option=<string>Pass options to receive-pack
OptionDescription
-q, --quietSuppress output
-v, --verboseVerbose output
--progressShow progress
ParameterDescription
<repository>Remote repository name or URL
<refspec>Local and remote refs to push
1. Validate: Check local commits and refs
2. Negotiate: Determine what to send to remote
3. Transfer: Send objects and update refs
4. Verify: Confirm successful push
5. Update: Set upstream tracking if requested
Fast-forward push:
Remote: A---B---C
Local: A---B---C---D
Result: A---B---C---D (both)
Force push (dangerous):
Remote: A---B---C---X
Local: A---B---C---D
Result: A---B---C---D (overwrites X)
Terminal window
# Push current branch to default remote
git push
# Push to specific remote
git push origin
# Push specific branch
git push origin main
# Push current branch and set upstream
git push -u origin main
# Push all branches
git push --all
# Push all tags
git push --tags
Terminal window
# Push new branch
git push -u origin feature-branch
# Delete remote branch
git push origin --delete old-branch
# Push multiple branches
git push origin main develop
# Mirror repository
git push --mirror origin
Terminal window
# Force push (dangerous - overwrites remote)
git push --force
# Force with lease (safer - checks remote state)
git push --force-with-lease
# Force specific branch
git push --force-with-lease origin main
Terminal window
# Preview what would be pushed
git push --dry-run
# Verbose dry run
git push --dry-run --verbose
# Check what tags would be pushed
git push --tags --dry-run
Terminal window
# Set upstream for current branch
git push --set-upstream origin feature-x
# Push and set upstream in one command
git push -u origin new-branch
# Change upstream remote
git branch --set-upstream-to=origin/main main
# Check upstream configuration
git branch -vv
Terminal window
# Sign all pushes
git push --signed
# Sign if remote supports it
git push --signed=if-asked
# Configure default signing
git config push.gpgSign true
# Use specific key
git config user.signingkey "your-key-id"
Terminal window
# Atomic push (all refs succeed or all fail)
git push --atomic origin main develop
# Push multiple refs atomically
git push --atomic --all
# Verify atomic behavior
git push --atomic --dry-run --verbose
Terminal window
# Pass options to remote hooks
git push -o ci.skip
# Multiple push options
git push -o merge_request.create -o merge_request.target=main
# Configure default push options
git config remote.origin.pushOption "ci.skip"
Terminal window
# Configure default push behavior
git config push.default simple # Push current branch
git config push.default upstream # Push upstream branch
git config push.default current # Push current branch to same name
git config push.default matching # Push all matching branches
# Configure per-remote
git config remote.origin.push refs/heads/main:refs/heads/main
git config remote.origin.push refs/heads/develop:refs/heads/develop
Terminal window
# Configure remote push URL
git remote set-url --push origin https://github.com/user/repo.git
# Separate push and fetch URLs
git remote set-url origin https://github.com/user/repo.git
git remote set-url --push origin git@github.com:user/repo.git
# Configure push refspecs
git config remote.origin.push refs/heads/*:refs/heads/*
Terminal window
# Enable push signing
git config push.gpgSign true
git config commit.gpgSign true
# Configure credential helpers
git config credential.helper store
git config credential.helper cache
# Set up SSH keys for push
ssh-keygen -t ed25519 -C "your-email@example.com"
ssh-add ~/.ssh/id_ed25519
#!/bin/bash
# CI/CD push workflow
ci_push_workflow() {
echo "=== CI Push Workflow ==="
# Configure Git for CI
git config user.name "CI Bot"
git config user.email "ci@example.com"
# Set remote URL with credentials
git remote set-url origin "https://$CI_TOKEN@github.com/user/repo.git"
# Push with verification
if git push --quiet --follow-tags; then
echo "✓ Push successful"
# Verify push
local remote_commit=$(git rev-parse HEAD)
local remote_head=$(git ls-remote origin HEAD | awk '{print $1}')
if [ "$remote_commit" = "$remote_head" ]; then
echo "✓ Push verified - commits match"
return 0
else
echo "✗ Push verification failed"
return 1
fi
else
echo "✗ Push failed"
return 1
fi
}
ci_push_workflow
Terminal window
# Release push workflow
release_push() {
local version="$1"
local branch="${2:-main}"
echo "=== Release Push: v$version ==="
# Create and push release tag
git tag -a "v$version" -m "Release v$version"
# Push branch and tags
git push origin "$branch"
git push origin "v$version"
# Create release branch if needed
if [ "$branch" != "main" ] && [ "$branch" != "master" ]; then
git push origin "$branch"
fi
# Verify release
if git ls-remote --tags origin | grep -q "v$version"; then
echo "✓ Release v$version published successfully"
else
echo "✗ Release verification failed"
return 1
fi
}
release_push "2.1.0" "release/v2.1"
Terminal window
# Team push workflow
team_push_workflow() {
local branch="${1:-$(git branch --show-current)}"
echo "=== Team Push Workflow: $branch ==="
# Check for unpushed commits
local ahead_behind
ahead_behind=$(git rev-list --left-right --count "HEAD...origin/$branch" 2>/dev/null || echo "0 0")
local ahead=$(echo "$ahead_behind" | awk '{print $1}')
if [ "$ahead" -gt 0 ]; then
echo "Found $ahead unpushed commits"
# Run pre-push checks
if command -v pre-push-hook >/dev/null 2>&1; then
if ! pre-push-hook; then
echo "✗ Pre-push checks failed"
return 1
fi
fi
# Push with upstream tracking
if git push --set-upstream origin "$branch"; then
echo "✓ Branch $branch pushed successfully"
# Notify team (if notification system exists)
# notify_team "Branch $branch updated with $ahead commits"
return 0
else
echo "✗ Push failed"
return 1
fi
else
echo "Branch $branch is already up to date"
fi
}
team_push_workflow "feature/dark-mode"
Terminal window
# Check remote URL
git remote -v
# Test authentication
ssh -T git@github.com 2>/dev/null && echo "SSH OK" || echo "SSH failed"
# Update credentials
git config credential.helper store
# Use personal access token
git remote set-url origin "https://oauth-token@github.com/user/repo.git"
Terminal window
# Check why push was rejected
git status
# Shows: Your branch is behind 'origin/main' by X commits
# Fetch and merge/rebase first
git fetch origin
git rebase origin/main # or git merge origin/main
# Then push
git push
Terminal window
# Safe force push with lease
git push --force-with-lease
# Check what would be overwritten
git log --oneline origin/main..HEAD
# Force push with confirmation
read -p "Force push will overwrite remote commits. Continue? (y/N) " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]; then
git push --force-with-lease
fi
Terminal window
# Increase buffer size
git config http.postBuffer 524288000 # 500MB
# Compress better
git config core.compression 9
git config pack.compression 9
# Use shallow push for large repos
git push --depth=1
# Split large pushes
git push origin main --no-thin # Disable delta compression
Terminal window
# Check repository permissions
curl -s https://api.github.com/repos/user/repo | jq .permissions
# Verify branch protection rules
# Check if force push is allowed
# Verify required status checks
# Use different remote if needed
git remote add fork git@github.com:your-fork/repo.git
git push fork main
Terminal window
# Skip hooks for urgent pushes
git push --no-verify
# Debug hook issues
GIT_TRACE=1 git push
# Check server-side hooks
# Review pre-receive, update, post-receive hooks
#!/bin/bash
# Complete feature branch push workflow
feature_branch_push() {
local feature_branch="$1"
local target_branch="${2:-main}"
echo "=== Feature Branch Push: $feature_branch ==="
# Switch to feature branch
git checkout "$feature_branch"
# Ensure branch is up to date with target
git fetch origin
git rebase "origin/$target_branch"
# Run tests before push
if command -v run-tests >/dev/null 2>&1; then
if ! run-tests; then
echo "✗ Tests failed - not pushing"
return 1
fi
fi
# Push feature branch
if git push --set-upstream origin "$feature_branch"; then
echo "✓ Feature branch $feature_branch pushed"
# Create pull request hint
echo ""
echo "Next steps:"
echo "1. Create pull request from $feature_branch to $target_branch"
echo "2. Request code review"
echo "3. Wait for CI checks to pass"
echo "4. Merge when approved"
return 0
else
echo "✗ Push failed"
return 1
fi
}
feature_branch_push "feature/user-authentication" "develop"
Terminal window
# Enterprise push with compliance
enterprise_push() {
local environment="$1"
local version="$2"
echo "=== Enterprise Push: $environment v$version ==="
# Compliance checks
if ! security_scan_passed "$version"; then
echo "✗ Security scan failed"
return 1
fi
if ! compliance_check_passed "$version"; then
echo "✗ Compliance check failed"
return 1
fi
# Select target remote based on environment
case "$environment" in
"staging")
remote="staging"
branch="staging"
;;
"production")
remote="production"
branch="main"
;;
*)
echo "Unknown environment: $environment"
return 1
;;
esac
# Tag release
git tag -a "v$version-$environment" -m "Deploy v$version to $environment"
# Push with verification
if git push "$remote" "$branch" --tags --signed; then
echo "✓ Successfully deployed v$version to $environment"
# Log deployment
log_deployment "$environment" "$version" "$(date)" "$USER"
# Trigger post-deployment tasks
trigger_post_deploy "$environment" "$version"
return 0
else
echo "✗ Deployment failed"
return 1
fi
}
enterprise_push "production" "2.1.0"
Terminal window
# Push to multiple related repositories
multi_repo_push() {
local repos_file="$1"
local branch="${2:-main}"
echo "=== Multi-Repository Push ==="
while IFS='|' read -r repo_path remote_url; do
echo "Processing: $repo_path"
if [ -d "$repo_path/.git" ]; then
cd "$repo_path"
# Set remote if needed
if ! git remote | grep -q "^origin$"; then
git remote add origin "$remote_url"
fi
# Push branch
if git push origin "$branch"; then
echo "$repo_path pushed successfully"
else
echo "$repo_path push failed"
fi
cd - >/dev/null
else
echo "Repository not found: $repo_path"
fi
done < "$repos_file"
}
# Repository configuration file format:
# /path/to/repo1|https://github.com/org/repo1.git
# /path/to/repo2|https://github.com/org/repo2.git
multi_repo_push "repositories.txt" "main"

What’s the difference between git push and git pull?

Section titled “What’s the difference between git push and git pull?”

git push sends local commits to remote repository; git pull fetches remote commits and merges them locally. Push publishes work, pull synchronizes with others’ work.

Use git push -u origin branch-name to push the branch and set upstream tracking. The -u flag establishes the tracking relationship for future pushes.

Checks if remote refs haven’t changed since last fetch before force pushing. Safer than —force as it prevents overwriting unexpected remote changes.

Use git push origin —delete branch-name to remove the branch from remote. Local branch remains until deleted with git branch -d.

Yes, configure multiple remotes and push to each: git remote add upstream url, then git push origin && git push upstream.

What’s the impact of force push on collaborators?

Section titled “What’s the impact of force push on collaborators?”

Force push rewrites remote history, causing issues for collaborators. They must rebase/reset their local branches. Avoid on shared branches.

Set push.default=simple (Git 2.0+) to push only current branch to matching remote branch. Other options: upstream, current, matching.

What happens if push fails with non-fast-forward?

Section titled “What happens if push fails with non-fast-forward?”

Remote has commits you don’t have locally. Fetch and merge/rebase first, then push. Or use —force-with-lease if you intend to overwrite.

No, push sends committed objects. Uncommitted changes stay local. Use git stash to temporarily store uncommitted work.

Increase http.postBuffer, use compression, disable delta for large files, or push in smaller batches. Consider using Git LFS for large files.

What’s the relationship between push and tracking branches?

Section titled “What’s the relationship between push and tracking branches?”

Push updates remote refs. Tracking branches (—set-upstream/-u) establish relationship between local and remote branches for future operations.

  1. Code Publishing: Share local commits with remote repositories and team members
  2. Branch Management: Create, update, and delete remote branches
  3. Release Deployment: Push tags and release branches to production environments
  4. Collaborative Development: Synchronize feature branches with team repositories
  5. CI/CD Integration: Automated pushing of build artifacts and deployment commits
  6. Repository Mirroring: Maintain synchronized copies across multiple remote locations