git remoteとは、ローカルリポジトリに「リモートリポジトリの名前とURLの組」を登録・変更・削除するコマンドです。 origin はその名前のひとつで、git clone したときに自動で付く既定の名前にすぎません。URLを変えたいときは git remote set-url、追加は git remote add、削除は git remote remove を使います。

この記事では、remote の全操作を Git 2.43.0 で実際に動かした実行結果つき で一覧にします。さらに、push したときに出る ! [rejected](non-fast-forward、fetch first、stale info)や src refspec main does not match any、has no upstream branch などを ローカルの bare リポジトリで再現 し、エラーメッセージの原文・原因・解決コマンドを対応表にまとめました。最後に、--force-with-lease と --force の違いも、同じ状況で両方を実行して比べます。

git remoteとpushエラーの早見表

やりたいこと別のコマンド

やりたいこと コマンド 補足
登録済みのリモートをURLつきで見る git remote -v fetch用とpush用の2行が出る
リモートを追加する git remote add origin <URL> 名前は自由。最初の1つは origin が慣例
URLを変更する git remote set-url origin <新URL> HTTPS⇔SSH の切り替えもこれ
URLだけ取り出す git remote get-url origin スクリプト向き
push 先だけ変える git remote set-url --push origin <URL> fetch 元はそのまま
push 先を2か所にする git remote set-url --add --push origin <URL> 1回の push で両方へ送る
名前を変える git remote rename origin upstream 追跡ブランチ名も一緒に変わる
削除する git remote remove origin rm でも同じ
詳しい状態を見る git remote show origin リモートに問い合わせて表示
消えたブランチの追跡を掃除 git remote prune origin git fetch --prune でも同じ
本家を追加する(fork 運用) git remote add upstream <URL> git fetch upstream で取得

pushエラーの対応表(すべて再現して確認)

エラーメッセージ(原文の要点) 原因 解決コマンド
! [rejected] main -> main (fetch first) リモートに、手元にまだ無いコミットがある git pull --rebase origin main → git push
! [rejected] main -> main (non-fast-forward) fetch 済みだが、手元の履歴がリモートの続きになっていない git pull --rebase origin main → git push
! [rejected] ... (stale info) --force-with-lease の確認で、リモートが想定より進んでいた git fetch → 取り込んでから再度 push
error: remote origin already exists. 同じ名前のリモートが登録済み git remote set-url origin <URL>
error: src refspec main does not match any その名前のローカルブランチが無い/コミットが1つも無い git branch で名前を確認、または最初のコミットを作る
fatal: The current branch main has no upstream branch. 上流ブランチ(push 先の対応づけ)が未設定 git push -u origin main
fatal: 'origin' does not appear to be a git repository リモート未登録、またはURLの打ち間違い git remote -v で確認し add/set-url
fatal: No configured push destination. リモートが1つも無い git remote add origin <URL>
! [remote rejected] ... (non-fast-forward) サーバー側の設定で履歴の書き換えを受け付けていない 管理者に確認、または通常のコミットで直す
Permission denied (publickey). SSH 鍵が未登録・未ロード(公式ドキュメントで確認) ssh -T git@github.com で接続確認

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「git remoteの変更・追加・削除とpush rejectedの対処法」

検証環境と再現用のセットアップ

この記事の出力は、次の環境で取得しました。GitHub などの外部サービスには接続せず、同じマシン上の bare リポジトリ(作業ツリーを持たない、サーバー役のリポジトリ) をリモートとして使っています。手元でも同じ手順で試せます。

項目 内容
Git 2.43.0(Linux)
公式ドキュメントの最新版 2.55.0(2026-06-29 更新の git-push マニュアルで確認)
リモート役 git init --bare で作ったローカルリポジトリ
メッセージの言語 英語(LC_ALL=C)
# サーバー役(bare リポジトリ)を3つ作る
mkdir -p ~/remote-lab/server ~/remote-lab/work
cd ~/remote-lab
git init --bare server/shop.git
git init --bare server/shop-fork.git
git init --bare server/backup.git

# 作業用リポジトリを作り、最初のコミットを置く
cd work
git init shop && cd shop
echo "# shop" > README.md
git add . && git commit -m "first commit"

以降は ~/remote-lab/work/shop の中で実行しています。一部の出力に含まれる長い絶対パスは /work/server.git に短縮して載せています。リモートのURLは相対パス ../../server/shop.git ですが、GitHub の URL に置き換えても操作は同じです。

git remoteの基本操作を実行結果で確認する

リモートを確認する(git remote -v)

リモートを登録する前は、何も表示されません。

$ git remote -v
$

この状態で git push すると、次のように案内されます。

$ git push
fatal: No configured push destination.
Either specify the URL from the command-line or configure a remote repository using

    git remote add <name> <url>

and then push using the remote name

    git push <name>

「origin が見つからない」系のメッセージが出たら、まず git remote -v で登録内容を見る のが近道です。

リモートを追加する(git remote add)

$ git remote add origin ../../server/shop.git
$ git remote -v
origin  ../../server/shop.git (fetch)
origin  ../../server/shop.git (push)

1つのリモートに対して fetch 用と push 用の2行 が表示されます。通常は同じURLですが、後で説明するように別々にもできます。

同じ名前でもう一度 add すると、次のエラーになります(終了コードは 3)。

$ git remote add origin ../../server/backup.git
error: remote origin already exists.

すでにある名前のURLを差し替えたいときは add ではなく set-url を使います。別のリモートとして並べたいなら、backup など別の名前で add します。

初回のpushと上流ブランチ(-u)

リモートを登録した直後に、引数なしで git push すると次のようになります。

$ git push
fatal: The current branch main has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin main

To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.

上流ブランチ(upstream branch)とは、「このローカルブランチは、どのリモートのどのブランチと対応するか」という対応づけ です。-u(--set-upstream)を付けて一度 push すると記録されます。

$ git push -u origin main
To ../../server/shop.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.
$ git status -sb
## main...origin/main

毎回 -u を付けるのが手間なら、push.autoSetupRemote を有効にすると、上流が無いブランチでも git push だけで設定されます。次の出力は一時的に設定を渡して試したものです。

$ git switch -c feature/new
$ git -c push.autoSetupRemote=true push
To /work/server.git
 * [new branch]      feature/new -> feature/new
branch 'feature/new' set up to track 'origin/feature/new'.

常に有効にするなら git config --global push.autoSetupRemote true です。設定項目の全体像は、既存記事「git config設定一覧とおすすめalias」にまとめています。

URLを変更する(git remote set-url)

リポジトリの引っ越しや、HTTPS と SSH の切り替えで使います。

$ git remote set-url origin https://github.com/example/shop.git
$ git remote -v
origin  https://github.com/example/shop.git (fetch)
origin  https://github.com/example/shop.git (push)

存在しない名前を指定すると、次のエラーになります。

$ git remote set-url nothere x
error: No such remote 'nothere'

名前を変える(git remote rename)

$ git remote add upstream ../../server/shop-fork.git
$ git remote rename upstream source
$ git remote -v
origin  ../../server/shop.git (fetch)
origin  ../../server/shop.git (push)
source  ../../server/shop-fork.git (fetch)
source  ../../server/shop-fork.git (push)

rename すると、.git/config の見出しだけでなく リモート追跡ブランチ(upstream/main → source/main)や、各ブランチの上流設定も一緒に書き換わります。 手で設定ファイルを直すより、コマンドに任せるほうが漏れがありません。

削除する(git remote remove)

$ git remote remove source
$ git remote remove source
error: No such remote: 'source'

1回目は何も表示されずに成功し、2回目は「その名前は無い」というエラーになります。削除されるのは手元の登録とリモート追跡ブランチだけで、サーバー上のリポジトリには何も起きません。 安心して試せます。

詳しい状態を見る(git remote show)

$ git remote show origin
* remote origin
  Fetch URL: ../../server/shop.git
  Push  URL: ../../server/shop.git
  HEAD branch: main
  Remote branch:
    main tracked
  Local branch configured for 'git pull':
    main merges with remote main
  Local ref configured for 'git push':
    main pushes to main (up to date)
表示 意味
Fetch URL / Push URL 取得元と送信先のURL
HEAD branch リモートの既定ブランチ
tracked 追跡中のリモートブランチ
stale リモートでは消えたが、手元に追跡ブランチが残っている
up to date / fast-forwardable / local out of date そのまま push できるかどうかの目安

show はリモートに実際に問い合わせます。ネットワークを使わずに設定だけ見たいときは git remote show -n origin を使います。

消えたブランチの追跡を掃除する(git remote prune)

別の人がリモートのブランチを削除しても、手元の origin/feature/login は git fetch だけでは消えません。 次の出力は、同僚役のクローンから git push origin --delete feature/login を実行したあとの様子です。

$ git fetch origin
$ git branch -r
  origin/feature/login
  origin/main
$ git remote show origin
* remote origin
  ...
  Remote branches:
    main                              tracked
    refs/remotes/origin/feature/login stale (use 'git remote prune' to remove)

--dry-run で対象を確認してから掃除します。

$ git remote prune origin --dry-run
Pruning origin
URL: ../../server/shop.git
 * [would prune] origin/feature/login
$ git remote prune origin
Pruning origin
URL: ../../server/shop.git
 * [pruned] origin/feature/login
$ git branch -r
  origin/main

毎回の fetch で自動的に掃除したい場合は git fetch --prune、常に有効にするなら git config --global fetch.prune true が便利です。

.git/configの中身を読む

git remote の各コマンドは、リポジトリ内の .git/config を書き換えています。origin を登録して git push -u origin main した直後の中身は次のとおりです。

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[remote "origin"]
    url = ../../server/shop.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
    remote = origin
    merge = refs/heads/main
行 意味 書き換えるコマンド
[remote "origin"] リモート名 remote add / rename / remove
url = ... 取得元(push 先を兼ねる) remote set-url
pushurl = ... push 先だけ別にする場合のURL remote set-url --push
fetch = +refs/heads/*:refs/remotes/origin/* リモートの全ブランチを origin/名前 として取り込む指定(refspec) remote add が自動で書く
[branch "main"] の remote / merge main の上流ブランチ push -u / branch --set-upstream-to

fetch の行の先頭にある + は、「リモート追跡ブランチは早送りでなくても更新してよい」という意味 です。リモートで履歴が書き換えられても、origin/main は fetch のたびにリモートと同じ位置に合わせられます。

設定ファイルをエディタで直接編集しても動きますが、rename のように関連箇所が複数あるものはコマンドのほうが安全です。値を1つ確認するだけなら次のように取り出せます。

$ git config --get remote.origin.url
../../server/shop.git

HTTPSとSSHを切り替える

GitHub の公式ドキュメントで確認した URL の形式は次の2種類です。

方式 URLの形 認証
HTTPS https://github.com/OWNER/REPOSITORY.git 個人アクセストークン(PAT)や認証ヘルパー
SSH git@github.com:OWNER/REPOSITORY.git SSH 鍵

切り替えは set-url に新しい形のURLを渡すだけです。

$ git remote set-url origin git@github.com:example/shop.git
$ git config --get remote.origin.url
git@github.com:example/shop.git

HTTPS に戻すときも同じ要領です。

git remote set-url origin https://github.com/example/shop.git

切り替えたあとは git fetch origin を1回実行して、認証が通るか確かめる と安心です。fetch は手元の作業内容を変えないので、確認に向いています。

remote -v の表示と設定値が違って見えるとき

検証環境では、SSH 形式で set-url したのに git remote -v には HTTPS のURLが表示されました。調べると、環境側で url.https://github.com/.insteadOf git@github.com: という URL の読み替え設定(insteadOf) が入っていました。

確認コマンド 表示されるもの
git config --get remote.origin.url .git/config に保存された値そのまま
git remote -v / git remote get-url origin insteadOf を適用したあとの、実際に接続するURL
git config --show-origin --get-regexp 'url\..*' 読み替え設定がどこで定義されているか

「set-url したのに表示が変わらない」と感じたら、insteadOf の設定を確認する と原因が見つかります。

認証まわりのエラー(公式ドキュメントで確認)

次の2つは外部サービスへの接続が必要なため、この記事では再現していません。GitHub の公式ドキュメントの記載をもとに整理します。

メッセージ 状況 確認すること
Permission denied (publickey). SSH でサーバーが接続を受け付けなかった ssh -vT git@github.com で接続確認、ssh-add -l -E sha256 で鍵がロード済みか、アカウントに公開鍵を登録済みか。接続ユーザー名は git
HTTPS でパスワードを求められる パスワード認証は廃止済み パスワード欄に個人アクセストークンを入力する、または SSH に切り替える

鍵の作成から登録までの手順は、既存記事「SSH鍵の作成とGitHub接続|Permission deniedの対処法」で順を追って説明しています。

複数のリモートを使う(originとupstream)

forkした本家をupstreamとして追加する

自分用のコピー(fork)を origin、本家を upstream と呼ぶのが広く使われている習慣です。

$ git remote add upstream ../../server/shop-fork.git
$ git remote
origin
upstream
$ git remote -v
origin  ../../server/shop.git (fetch)
origin  ../../server/shop.git (push)
upstream    ../../server/shop-fork.git (fetch)
upstream    ../../server/shop-fork.git (push)

本家の変更を取り込む流れは次のとおりです。

git fetch upstream                # 本家の最新を取得
git switch main
git merge --ff-only upstream/main # 自分の main を本家に追いつかせる
git push origin main              # 自分の fork にも反映

push先だけ変える(--push)

本家には取得だけして、うっかり push しないようにしたい場合は、push 用のURLに存在しない値を入れておく方法があります。

$ git remote set-url --push upstream no_push
$ git remote -v
origin  ../../server/shop.git (fetch)
origin  ../../server/shop.git (push)
upstream    ../../server/shop-fork.git (fetch)
upstream    no_push (push)
$ git push upstream main
fatal: 'no_push' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

.git/config には pushurl = no_push の1行が加わります。fetch は今までどおり動き、push だけが止まる ので、読み取り専用のリモートとして扱えます。

1回のpushで2か所に送る(--add --push)

バックアップ用のリポジトリにも同時に送りたいときは、push 用URLを2つ登録します。

$ git remote set-url --add --push origin ../../server/shop.git
$ git remote set-url --add --push origin ../../server/backup.git
$ git remote -v
origin  ../../server/shop.git (fetch)
origin  ../../server/shop.git (push)
origin  ../../server/backup.git (push)
$ git push origin main
Everything up-to-date
To ../../server/backup.git
 * [new branch]      main -> main

ポイントは、元のURLも --add --push で登録し直すこと です。pushurl を1つでも設定すると、push では url が使われなくなるためです。設定ファイルは次のようになります。

[remote "origin"]
    url = ../../server/shop.git
    fetch = +refs/heads/*:refs/remotes/origin/*
    pushurl = ../../server/shop.git
    pushurl = ../../server/backup.git

元に戻すには git config --unset-all remote.origin.pushurl を実行します。

push rejectedを再現して直す

ここからは、push が受け付けられない状況を1つずつ再現します。登場人物は、同じリポジトリをクローンした Taro と Hanako の2人です。

rejectedが起きる仕組み

gitGraph
    commit id: "first commit"
    branch hanako
    commit id: "hanako: update README"
    checkout main
    commit id: "taro: add taro.txt"

通常の push は「リモートの先端に、自分のコミットを継ぎ足すだけ」で済む場合(fast-forward、早送り)にだけ成功します。 上の図のように、Hanako が先に push したあとで Taro が別のコミットを push しようとすると、継ぎ足しでは済まないので Git は受け付けません。これは、Hanako のコミットがリモートから見えなくなるのを防ぐための動作です。

(fetch first):リモートに未取得のコミットがある

Hanako が先に push し、Taro はまだ fetch していない状態です。

$ git push origin main
To ../../server/shop.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to '../../server/shop.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

(non-fast-forward):取得済みだが取り込んでいない

git fetch だけして、もう一度 push すると、かっこの中の理由が変わります。

$ git fetch origin
From ../../server/shop
   d23c20d..3550478  main       -> origin/main
$ git push origin main
To ../../server/shop.git
 ! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to '../../server/shop.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
$ git status -sb
## main...origin/main [ahead 1, behind 1]
理由 手元の状態 違い
fetch first リモートの新しいコミットをまだ取得していない Git は「リモートに知らないコミットがある」ことだけ分かっている
non-fast-forward 取得済みで、ahead 1, behind 1 のように枝分かれしている 追跡ブランチと比べて、継ぎ足しにならないと判定された

どちらも解決方法は同じで、リモートの変更を取り込んでから push し直します。

解決:取り込んでからpushする

$ git pull --rebase origin main
From ../../server/shop
 * branch            main       -> FETCH_HEAD
Successfully rebased and updated refs/heads/main.
$ git push origin main
To ../../server/shop.git
   3550478..5fe34cd  main -> main

取り込み方は2通りあります。

方法 コマンド 履歴 向いている場面
リベース git pull --rebase origin main 一直線になる 自分のコミットがまだ共有されていないとき
マージ git pull --no-rebase origin main マージコミットができる 枝分かれの記録を残したいとき

違いの詳細は既存記事「git mergeとrebaseの違い」で扱っています。途中でコンフリクトが出たら、該当ファイルを直して git add → git rebase --continue で続けます。

git pullで「divergent branches」と表示されたとき

取り込み方を決めていない状態で、枝分かれしたブランチに git pull すると、次のように尋ねられます。

$ git pull
From ../../server/shop
   5fe34cd..5008c26  main       -> origin/main
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint: 
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
...
fatal: Need to specify how to reconcile divergent branches.

git pull --rebase のように毎回指定するか、git config --global pull.rebase true などで既定を決めておくと、この表示は出なくなります。

pushの出力記号の読み方

push の結果は、行頭の記号で読み取れます(意味は公式マニュアルで確認)。

記号 意味 この記事での出力例
(空白) 早送りで push できた 3550478..5fe34cd main -> main
* 新しいブランチやタグを作った * [new branch] main -> main
+ 強制更新した + 10430ee...b57c742 feature/cart -> feature/cart (forced update)
- 削除した - [deleted] feature/login
! 受け付けられなかった ! [rejected] main -> main (fetch first)
= すでに最新(--verbose で表示) ―

..(ドット2つ)は早送り、...(ドット3つ)は強制更新 という違いもあります。

そのほかのpushエラーを再現する

src refspec main does not match any

$ git push origin master
error: src refspec master does not match any
error: failed to push some refs to '../../server/shop.git'

「push 元として指定した名前(src refspec)に当てはまるものが、手元に無い」 という意味です。再現できた原因は次の2つでした。

原因 確認方法 解決
ブランチ名が違う(main と master など) git branch で現在の名前を見る 正しい名前で push する。名前を変えるなら git branch -m main
まだ1つもコミットしていない git log が does not have any commits yet になる git add . → git commit -m "first commit" のあとで push

2つ目は、git init と git remote add の直後にそのまま push したときに起きます。空のリポジトリで試した結果が次の出力です。

$ git init && git remote add origin ../../server/shop.git
$ git push -u origin main
error: src refspec main does not match any
error: failed to push some refs to '../../server/shop.git'

does not appear to be a git repository

リモート名が未登録のとき、またはURLに打ち間違いがあるときに出ます。

$ git push origin main
fatal: '../server-typo.git' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

git remote -v でURLを見直し、git remote set-url origin <正しいURL> で直します。メッセージの後半は権限が足りない場合にも共通で出るため、まずURLの綴り、次にアクセス権の順で確認する と切り分けやすくなります。

上流ブランチと名前が違うとき

ローカルブランチ名と、上流に設定したリモートブランチ名が違うと、引数なしの git push は確認を求めます。

$ git push
fatal: The upstream branch of your current branch does not match
the name of your current branch.  To push to the upstream branch
on the remote, use

    git push origin HEAD:feature/cart

To push to the branch of the same name on the remote, use

    git push origin HEAD
...

案内のとおり、送り先を明示すれば push できます。git push origin HEAD は「今いるブランチを、同じ名前で送る」という書き方で、ブランチ名を打たずに済むので覚えておくと便利です。

タグが (already exists) になる

$ git push origin v1
To ../../server/shop.git
 ! [rejected]        v1 -> v1 (already exists)
error: failed to push some refs to '../../server/shop.git'
hint: Updates were rejected because the tag already exists in the remote.

リモートにあるタグと同じ名前で、別のコミットを指すタグを push したときの表示です。公開済みのタグは動かさず、v1.0.1 のように新しい名前を付ける のが分かりやすい運用です。命名の考え方は既存記事「git tagとセマンティックバージョニング」を参照してください。

--force-with-leaseと--forceの違いを再現する

git commit --amend や git rebase で push 済みのコミットを書き換えると、通常の push は non-fast-forward になります。 このときに使うのが強制 push です。作業ブランチ feature/cart で、3つの状況を試しました。

状況A:自分だけが使うブランチでコミットを書き換えた

$ git commit --amend -m "cart: add cart page"
$ git push origin feature/cart
To /work/server.git
 ! [rejected]        feature/cart -> feature/cart (non-fast-forward)
error: failed to push some refs to '/work/server.git'
...
$ git push --force-with-lease origin feature/cart
To /work/server.git
 + 10430ee...b57c742 feature/cart -> feature/cart (forced update)

リモートの先端が、手元の追跡ブランチ origin/feature/cart と同じ位置だったので、強制更新が通りました。

状況B:その間にHanakoがpushしていた

Hanako が同じブランチにテストを追加して push したあと、Taro が(fetch せずに)もう一度コミットを書き換えて強制 push します。

$ git push --force-with-lease origin feature/cart
To /work/server.git
 ! [rejected]        feature/cart -> feature/cart (stale info)
error: failed to push some refs to '/work/server.git'

stale info は、「手元が覚えているリモートの位置と、実際のリモートの位置が違う」という意味 です。Hanako のコミットは残ったままです。

状況C:同じ場面で--forceを使うと

比較のため、サーバーのコピーに対して --force を実行しました。

$ git --git-dir=../server-copy.git log --oneline -3 feature/cart
13bf495 hanako: more tests
97cd66f hanako: add cart test
b57c742 cart: add cart page

$ git push --force ../server-copy.git feature/cart
To ../server-copy.git
 + 13bf495...5ed74d5 feature/cart -> feature/cart (forced update)

$ git --git-dir=../server-copy.git log --oneline -3 feature/cart
5ed74d5 cart: add cart page (v3)
b57c742 cart: add cart page
512bbbc first commit

Hanako の2つのコミットが、ブランチの履歴から見えなくなりました。同じ状況で元のサーバーに --force-with-lease を使った場合は、状況Bと同じく stale info で止まりました。

オプション 確認する内容 他の人のコミットがあるとき
--force 何も確認しない そのまま上書きする
--force-with-lease リモートの先端が、手元の追跡ブランチと同じか stale info で止まる
--force-with-lease --force-if-includes 上に加えて、追跡ブランチの内容を手元に取り込み済みか 取り込んでいなければ止まる

fetchしたあとは--force-if-includesを足す

--force-with-lease は「追跡ブランチと同じか」を見るので、fetch して追跡ブランチだけが最新になると、取り込んでいなくても通ってしまいます。 --dry-run(実際には送らない確認モード)で試した結果です。

$ git fetch origin
   b57c742..97cd66f  feature/cart -> origin/feature/cart
$ git push --force-with-lease --dry-run origin feature/cart
To /work/server.git
 + 97cd66f...a77c6d7 feature/cart -> feature/cart (forced update)

$ git push --force-with-lease --force-if-includes --dry-run origin feature/cart
To /work/server.git
 ! [rejected]        feature/cart -> feature/cart (remote ref updated since checkout)
error: failed to push some refs to '/work/server.git'
hint: Updates were rejected because the tip of the remote-tracking branch has
hint: been updated since the last checkout. If you want to integrate the
hint: remote changes, use 'git pull' before pushing again.

エディタや GUI ツールが裏で自動的に fetch している環境では、気づかないうちにこの状態になります。公式マニュアルにも、引数なしの --force-with-lease はバックグラウンドの fetch と相性に注意が必要だと書かれています。--force-if-includes を一緒に付けておくと、取り込み漏れに気づけます。

強制pushの安全な手順

# 1. リモートの最新を取得して、差分を確認する
git fetch origin
git log --oneline HEAD..origin/feature/cart   # 自分に無いコミットがあれば表示される

# 2. 表示されたコミットがあれば取り込む
git rebase origin/feature/cart

# 3. 確認つきで強制 push する
git push --force-with-lease --force-if-includes origin feature/cart

毎回打つのが長いので、alias にしておくと使いやすくなります。

git config --global alias.pushf "push --force-with-lease --force-if-includes"

期待する位置を明示する書き方もあります。公式マニュアルで確認した3つの形式は次のとおりです。

形式 確認する内容
--force-with-lease push 対象すべてについて、追跡ブランチと同じ位置か
--force-with-lease=<ブランチ> 指定したブランチだけ、追跡ブランチと同じ位置か
--force-with-lease=<ブランチ>:<期待値> 指定したブランチが、明示したコミットと同じ位置か(最も厳密)

強制pushを使う場面の判断表

状況 おすすめの方法
自分だけが使う作業ブランチで、コミットを整理した --force-with-lease --force-if-includes
複数人が使うブランチで、直前のコミットを直したい 書き換えずに、修正のコミットを追加する(git revert も選択肢)
main などの共有ブランチ 強制 push は使わず、通常の push か プルリクエストで反映する
サーバーが [remote rejected] を返す ブランチ保護の設定を管理者に確認する

最後の行は、サーバー側で書き換えを受け付けない設定(receive.denyNonFastForwards)にして再現しました。

$ git push --force-with-lease origin feature/cart
remote: error: denying non-fast-forward refs/heads/feature/cart (you should pull first)
To /work/server.git
 ! [remote rejected] feature/cart -> feature/cart (non-fast-forward)
error: failed to push some refs to '/work/server.git'

[rejected] は手元の Git の判断、[remote rejected] はサーバー側の判断 です。後者はオプションを変えても通らないので、設定やルールを確認します。GitHub などのブランチ保護も、同じくサーバー側で止める仕組みです。

エラーが出たときの確認チェックリスト

上から順に確認すると、ほとんどの場合は原因にたどり着けます。

順番 確認すること コマンド
1 リモートの名前とURLは合っているか git remote -v
2 今いるブランチ名は何か git branch --show-current
3 コミットは1つ以上あるか git log --oneline -3
4 上流ブランチは設定されているか、何コミットずれているか git status -sb
5 リモートに未取得のコミットはあるか git fetch origin → git log --oneline HEAD..origin/main
6 認証は通るか git fetch origin、SSH なら ssh -T git@github.com
7 サーバー側のルール(ブランチ保護)はどうか [remote rejected] の表示を確認

よくある質問

Q. originという名前は変えてもよいですか? A. はい。origin は git clone が付ける既定の名前で、特別な機能はありません。git remote rename origin github のように変えると、追跡ブランチや上流設定も一緒に更新されます。チームで共有する手順書やスクリプトが origin を前提にしていることが多いので、そろえておくと説明が簡単になります。

Q. git remote removeを実行すると、GitHub上のリポジトリも消えますか? A. 消えません。削除されるのは、手元の .git/config の登録と、origin/main などのリモート追跡ブランチだけです。同じURLで git remote add し直して git fetch すれば、元の状態に戻ります。

Q. rejectedが出たら、とりあえずgit pullでよいですか? A. fetch first と non-fast-forward は、取り込めば解決します。git pull --rebase origin <ブランチ名> で取り込み、コンフリクトがあれば解消してから push し直してください。stale info や [remote rejected] は意味が違うので、この記事の対応表で原因を確認するのがおすすめです。

Q. --force-with-leaseを付ければ、共有ブランチでも強制pushしてよいですか? A. 他の人のコミットを上書きしにくくなりますが、すでに pull した人の手元とは履歴がずれます。強制 push は自分だけが使う作業ブランチに限り、共有ブランチは修正コミットの追加や git revert で直すと、全員の作業がそのまま続けられます。

まとめ

  • リモートの操作は git remote -v で確認、add で追加、set-url で変更、rename で改名、remove で削除。削除されるのは手元の登録だけ
  • remote origin already exists は set-url で差し替え、No such remote は名前の確認で解決する
  • HTTPS⇔SSH の切り替えも set-url。表示が変わらないときは insteadOf の読み替え設定を確認する
  • (fetch first) と (non-fast-forward) は、git pull --rebase で取り込んでから push し直す
  • src refspec ... does not match any はブランチ名の違いか、コミットが無い状態。has no upstream branch は git push -u origin <ブランチ> で解決する
  • 強制 push は --force-with-lease --force-if-includes を使うと、他の人のコミットがあるときに stale info で止まってくれる
  • [remote rejected] はサーバー側の判断。ブランチ保護などのルールを確認する

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「git remoteの変更・追加・削除とpush rejectedの対処法」

株式会社RJCでは、Gitのリモート操作やエラーの読み解き方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?