- Git
git pushの使い方|-u・rejected・強制pushの対処
git push とは、手元(ローカル)のコミットをリモートリポジトリへ送って反映するコマンドです。 初回は git push -u origin <ブランチ名> で送り先(upstream)を登録し、2回目以降は git push だけで済みます。rejected と表示されたら、ほとんどの場合は git pull --rebase でリモートの変更を取り込んでから push し直せば解決します。
この記事では、push で出会うエラーを実際に再現し、出力の全文と原因・解決コマンドを対応表にしました(Git 2.43.0、メッセージは英語表示、リモートはローカルのベアリポジトリ)。さらに、-u を毎回打たずに済む push.autoSetupRemote、--force・--force-with-lease・--force-if-includes の挙動の違いを、2人で同じブランチを使うシナリオで確かめています。タグの push やリモートブランチの削除を含むオプション早見表も付けました。
git pushの早見表
やりたいことからコマンドを引ける表です。
| やりたいこと | コマンド | 補足 |
|---|---|---|
| 新しいブランチを初めて push する | git push -u origin <ブランチ名> |
送り先(upstream)も同時に登録 |
| 2回目以降の push | git push |
upstream が登録済みなら引数は不要 |
| 今いるブランチを同名で push する | git push origin HEAD |
ブランチ名を打たずに済む |
-u を毎回打たずに済ませる |
git config --global push.autoSetupRemote true |
Git 2.37 以降 |
| 別名のリモートブランチへ push する | git push origin <ローカル名>:<リモート名> |
例:git push origin main:release |
| rejected になったとき | git pull --rebase → git push |
リモートの変更を取り込んでから送る |
| 履歴を書き換えた後に push する | git push --force-with-lease --force-if-includes |
自分専用ブランチで使う |
| タグを1つ push する | git push origin v1.0.0 |
ブランチの push ではタグは送られない |
| タグをまとめて push する | git push --tags |
注釈付きタグだけなら --follow-tags |
| リモートブランチを削除する | git push origin --delete <ブランチ名> |
git push origin :<ブランチ名> でも同じ |
| 実際には送らず結果だけ確認する | git push --dry-run |
-n でも同じ |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「git pushの使い方|-u・rejected・強制pushの対処」
git push の基本形と引数の意味
push の基本形は次のとおりです。
git push <リモート名> <ローカルブランチ名>:<リモートブランチ名>
| 書き方 | 意味 |
|---|---|
git push origin main |
ローカルの main を、origin の main へ送る(main:main の省略形) |
git push origin main:release |
ローカルの main を、origin の release へ送る |
git push origin HEAD |
今いるブランチを、origin の同名ブランチへ送る |
git push origin |
今いるブランチを origin へ送る(送り先ブランチは設定に従う) |
git push |
今いるブランチを、登録済みの upstream へ送る |
origin は、git clone したときに自動で付くリモートの名前です。upstream(上流ブランチ)とは、ローカルブランチごとに登録しておく「既定の送り先・取り込み元」のことで、これが登録されていると git push や git pull を引数なしで使えます。
push でコミットが届く流れを図にすると次のとおりです。
flowchart LR
W[作業ツリー] -- git add --> S[ステージ]
S -- git commit --> L[ローカルリポジトリ]
L -- git push --> R[リモートリポジトリ]
R -- git fetch / pull --> L
初回の push:-u で upstream を登録する
検証用に、練習用のリモートと作業用リポジトリを用意しました。同じ結果を試すなら次の準備をします。
git init --bare remote.git # 練習用のリモート
git clone remote.git alice && cd alice
git remote set-url origin ../remote.git
echo one > app.txt && git add . && git commit -m "初期コミット"
git push -u origin main
To ../remote.git
* [new branch] main -> main
branch 'main' set up to track 'origin/main'.
* [new branch] はリモートに新しいブランチができたこと、最後の行は upstream が登録されたことを示しています。
エラー1:has no upstream branch
新しいブランチを作り、コミットしてから引数なしで push します。
git switch -c feature/login
echo two >> app.txt && git commit -am "ログイン画面を追加"
git push
fatal: The current branch feature/login has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin feature/login
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.
「このブランチには送り先がまだ登録されていない」という案内です。 メッセージに書かれているコマンドをそのまま使えば解決します。-u は --set-upstream の短縮形です。
git push -u origin feature/login
To ../remote.git
* [new branch] feature/login -> feature/login
branch 'feature/login' set up to track 'origin/feature/login'.
登録の状態は git branch -vv で確認できます。角かっこの中が upstream です。
git branch -vv
* feature/login dedf4df [origin/feature/login] ログイン画面を追加
main e7cd654 [origin/main] 初期コミット
一度登録すれば、次からは git push だけで届きます。
echo three >> app.txt && git commit -am "入力チェックを追加"
git push
To ../remote.git
dedf4df..97fbbba feature/login -> feature/login
dedf4df..97fbbba は「リモートの先端が dedf4df から 97fbbba へ進んだ」という意味です。
push.autoSetupRemote で -u を省略する
ブランチを作るたびに -u origin <ブランチ名> を打つのが手間なら、push.autoSetupRemote を有効にすると、upstream がないブランチでも git push だけで同名のリモートブランチへ送り、登録まで済ませてくれます(Git 2.37 以降)。
git config --global push.autoSetupRemote true
git switch -c feature/search
echo s > s.txt && git add . && git commit -m "検索を追加"
git push
To ../remote.git
* [new branch] feature/search -> feature/search
branch 'feature/search' set up to track 'origin/feature/search'.
-u を付けていないのに、set up to track の行が出ています。git branch -vv でも登録を確認できました。
feature/login 7bdcf62 [origin/feature/login] Alice: 文言を修正
* feature/search 904aac6 [origin/feature/search] 検索を追加
main e7cd654 [origin/main] 初期コミット
| 方法 | 手数 | 向いている場面 |
|---|---|---|
git push -u origin <ブランチ名> |
ブランチごとに1回 | 設定を変えずに使いたい、送り先を毎回意識したい |
git push -u origin HEAD |
ブランチごとに1回(名前の入力なし) | ブランチ名が長い |
push.autoSetupRemote true |
最初に設定を1回 | ブランチを頻繁に作る |
エラー2:upstream の名前がローカルと違うとき
ローカルとリモートでブランチ名が違う形で upstream を登録すると、引数なしの git push は確認を求めて止まります。
git switch -c local-name
git push -u origin local-name:remote-name
echo x >> s.txt && git commit -am "x"
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:remote-name
To push to the branch of the same name on the remote, use
git push origin HEAD
To choose either option permanently, see push.default in 'git help config'.
To avoid automatically configuring an upstream branch when its name
won't match the local branch, see option 'simple' of branch.autoSetupMerge
in 'git help config'.
既定の push.default(simple)は、upstream の名前がローカルと同じときだけ引数なしの push を通す設定です。意図しないブランチへ送るのを防ぐための確認なので、案内どおり送り先を明示します。
git push origin HEAD:remote-name
To ../remote.git
904aac6..49ebe05 HEAD -> remote-name
毎回この形で送りたいなら git config push.default upstream に変える方法もありますが、名前をそろえておくほうが迷いにくくなります。
エラー3:src refspec ... does not match any
git push origin nothere
error: src refspec nothere does not match any
error: failed to push some refs to '../remote.git'
指定した名前のブランチ(またはタグ)がローカルに存在しないときのメッセージです。 ブランチ名の打ち間違いのほか、git init 直後でまだコミットが1つもない状態、既定ブランチが master なのに main を指定した場合にも出ます。git branch で実際の名前を確認すると解決します。
rejected を再現して対処する(2人作業のシナリオ)
ここからは、Alice と Bob が同じ feature/login ブランチを使う場面です。Bob が先にコミットを push した後、Alice が自分のコミットを push しようとします。
# Bob 側(別のクローン)
git clone remote.git bob && cd bob
git switch feature/login
echo bob >> bob.txt && git add . && git commit -m "Bob: ヘルプを追加"
git push
# Alice 側
cd ../alice && git switch feature/login
echo four >> app.txt && git commit -am "Alice: 文言を修正"
git push
エラー4:rejected (fetch first)
To ../remote.git
! [rejected] feature/login -> feature/login (fetch first)
error: failed to push some refs to '../remote.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.
(fetch first) は「リモートに、手元がまだ受け取っていないコミットがある」という意味です。 Alice のリポジトリは Bob のコミットの存在をまだ知りません。
エラー5:rejected (non-fast-forward)
git fetch でリモートの状態を受け取ってから、もう一度 push してみます。
git fetch
git status -sb
git push
From ../remote
97fbbba..c437003 feature/login -> origin/feature/login
## feature/login...origin/feature/login [ahead 1, behind 1]
To ../remote.git
! [rejected] feature/login -> feature/login (non-fast-forward)
error: failed to push some refs to '../remote.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.
今度はかっこの中が (non-fast-forward) に変わりました。fetch 済みなので Bob のコミットは知っているものの、手元のブランチにまだ取り込んでいない(behind 1)状態です。
| 表示 | 手元の状態 | 意味 |
|---|---|---|
(fetch first) |
リモートの新しいコミットを受け取っていない | まず fetch(または pull)が必要 |
(non-fast-forward) |
受け取ってはいるが、手元のブランチに取り込んでいない | 取り込み(merge か rebase)が必要 |
どちらも原因は同じで、リモートの先端が、手元の履歴の途中に含まれていないことです。push は、リモートの先端の続きにコミットを足す形(fast-forward)だけを通常は受け付けます。
flowchart LR
C[97fbbba 入力チェックを追加] --> B[c437003 Bob: ヘルプを追加 リモートの先端]
C --> A[Alice: 文言を修正 手元の先端]
解決:pull --rebase で取り込んでから push する
git pull --rebase
git push
git log --oneline -5
Successfully rebased and updated refs/heads/feature/login.
To ../remote.git
c437003..7bdcf62 feature/login -> feature/login
7bdcf62 Alice: 文言を修正
c437003 Bob: ヘルプを追加
97fbbba 入力チェックを追加
dedf4df ログイン画面を追加
e7cd654 初期コミット
git pull --rebase は、リモートの変更を受け取り、自分のコミットをその後ろに付け替える動きです。履歴が一直線になり、Bob のコミットの続きに Alice のコミットが並びました。git pull(マージ)でも解決できますが、その場合はマージコミットが1つ増えます。どちらを使うかはチームの方針に合わせてください。
同じファイルの同じ行を2人が変えていた場合は、取り込みの途中でコンフリクト(競合)の解消が必要になります。
エラーメッセージ別の原因と解決コマンド対応表
ここまでの再現結果と、後の章で扱うものをまとめた表です。 「再現」の列は、今回の検証で実際に出力を確認したかどうかを示します。
| 表示されるメッセージ(要点) | 原因 | 解決コマンド | 再現 |
|---|---|---|---|
fatal: The current branch ... has no upstream branch. |
送り先が未登録 | git push -u origin <ブランチ名> |
済 |
fatal: The upstream branch of your current branch does not match the name of your current branch. |
upstream の名前がローカルと違う | git push origin HEAD:<リモート名> |
済 |
error: src refspec <名前> does not match any |
その名前のブランチ・タグがローカルにない | git branch で名前を確認して指定し直す |
済 |
! [rejected] ... (fetch first) |
リモートに未取得のコミットがある | git pull --rebase → git push |
済 |
! [rejected] ... (non-fast-forward) |
取得済みだが手元に取り込んでいない/履歴を書き換えた | 取り込むなら git pull --rebase、書き換えを反映するなら git push --force-with-lease |
済 |
! [rejected] ... (stale info) |
--force-with-lease 使用時に、リモートが最後に確認した状態から進んでいた |
git fetch で差分を確認し、取り込んでから push |
済 |
! [rejected] ... (remote ref updated since checkout) |
--force-if-includes 使用時に、取得済みのリモートの変更が手元に取り込まれていない |
git pull --rebase → push |
済 |
! [remote rejected] ... (pre-receive hook declined) |
サーバー側のフック(ルール)が拒否した | 表示された理由に従う(別ブランチから反映するなど) | 済 |
! [remote rejected] ... (protected branch hook declined) |
ホスティングサービスのブランチ保護 | 作業ブランチを push してプルリクエストで反映 | 未実行 |
error: unable to delete '<名前>': remote ref does not exist |
削除対象がリモートに存在しない | git fetch --prune で一覧を更新して確認 |
済 |
強制 push の3つのオプションを比べる
git commit --amend や git rebase ですでに push したコミットを書き換えると、通常の push は non-fast-forward で止まります。 書き換えた履歴をリモートに反映するには強制 push が必要ですが、オプションによって「ほかの人のコミットを残せるかどうか」が変わります。
シナリオ
- Alice と Bob は、どちらも
7bdcf62 Alice: 文言を修正まで持っている - Bob が新しいコミット
77adc55 Bob: ヘルプを追記を push する - Alice はそれを知らずに、自分の直前のコミットを amend する
# Alice 側
git commit --amend -m "Alice: 文言を修正(表記ゆれ対応)"
[feature/login c2742c8] Alice: 文言を修正(表記ゆれ対応)
Date: Sat Oct 3 04:22:22 2026 +0900
1 file changed, 1 insertion(+)
この時点のリモートは 77adc55(Bob の追記)が先端です。ここから3通りの push を、同じ状態のコピーでそれぞれ試しました。
A. --force:確認なしで置き換える
git push --force
git --git-dir=../remote.git log --oneline feature/login -4
To ../remote.git
+ 77adc55...c2742c8 feature/login -> feature/login (forced update)
c2742c8 Alice: 文言を修正(表記ゆれ対応)
c437003 Bob: ヘルプを追加
97fbbba 入力チェックを追加
dedf4df ログイン画面を追加
リモートの履歴から 77adc55 Bob: ヘルプを追記 がなくなりました。 --force はリモートの状態を確認せず、手元の履歴でそのまま置き換えます。Alice は fetch していないので、Bob のコミットがあったこと自体に気づけません。
B. --force-with-lease:リモートが想定どおりのときだけ置き換える
git push --force-with-lease
To ../remote.git
! [rejected] feature/login -> feature/login (stale info)
error: failed to push some refs to '../remote.git'
(stale info) で止まりました。 --force-with-lease は、「手元のリモート追跡ブランチ(origin/feature/login)が指すコミット」と「実際のリモートの先端」が一致するときだけ強制 push を通します。Alice の origin/feature/login は 7bdcf62 のまま、実際のリモートは 77adc55 に進んでいるため、食い違いを検知して止めてくれます。
ただし、この確認は「最後に fetch した時点の情報」が基準です。エディタや GUI ツールが裏で自動的に fetch している環境を想定して、fetch した後にもう一度実行してみます。
git fetch
git push --force-with-lease
git --git-dir=../remote.git log --oneline feature/login -4
From ../remote
7bdcf62..77adc55 feature/login -> origin/feature/login
To ../remote.git
+ 77adc55...c2742c8 feature/login -> feature/login (forced update)
c2742c8 Alice: 文言を修正(表記ゆれ対応)
c437003 Bob: ヘルプを追加
97fbbba 入力チェックを追加
dedf4df ログイン画面を追加
fetch しただけ(取り込みはしていない)なのに、今度は push が通り、Bob の追記がリモートからなくなりました。 fetch によって origin/feature/login が 77adc55 に更新され、「想定どおり」と判定されたためです。--force-with-lease だけでは、自動 fetch がある環境で確認がすり抜けることがわかります。
C. --force-with-lease --force-if-includes:取り込み済みかどうかまで確認する
同じく fetch した後の状態で、--force-if-includes を足して実行します(Git 2.30 以降)。
git fetch
git push --force-with-lease --force-if-includes
To ../remote.git
! [rejected] feature/login -> feature/login (remote ref updated since checkout)
error: failed to push some refs to '../remote.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.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
今度は fetch 後でも止まりました。 --force-if-includes は、「リモート追跡ブランチの先端が、手元のブランチの履歴(reflog)に含まれているか」、つまり取得した変更を手元に取り込んだことがあるかを確認します。公式ドキュメント(git-push、今回 2.55.0 版のページで確認)にも、リモート追跡ブランチの先端がローカルブランチの reflog から到達できない場合は強制更新を拒否すると書かれています。このオプションは --force-with-lease と組み合わせたときに働きます。
案内に従って取り込んでから、もう一度 push します。
git pull --rebase
git log --oneline -5
git push --force-with-lease --force-if-includes
warning: skipped previously applied commit c2742c8
hint: use --reapply-cherry-picks to include skipped commits
hint: Disable this message with "git config advice.skippedCherryPicks false"
Successfully rebased and updated refs/heads/feature/login.
77adc55 Bob: ヘルプを追記
7bdcf62 Alice: 文言を修正
c437003 Bob: ヘルプを追加
97fbbba 入力チェックを追加
dedf4df ログイン画面を追加
Everything up-to-date
Bob の 77adc55 が残りました。なお、今回の amend はメッセージだけの変更だったため、rebase が「同じ内容のコミットがすでにリモート側にある」と判断して amend 後のコミットをスキップしています(warning の行)。その結果、手元はリモートと同じ履歴になり、push するものがなくなりました。ファイルの内容も変える amend であれば、Bob のコミットの後ろに付け替えられて push されます。共有ブランチで push 済みのコミットのメッセージだけを直したい場合は、書き換えずにそのままにしておくのがすっきりする、という実例にもなりました。
3つのオプションの比較表
| オプション | リモートの確認 | fetch 前に実行 | fetch 後(未取り込み)に実行 | 向いている場面 |
|---|---|---|---|---|
--force(-f) |
しない | 置き換える(Bob の追記がなくなる) | 置き換える | 自分しか使わないリポジトリ |
--force-with-lease |
リモート追跡ブランチと一致するか | 止まる (stale info) |
置き換える(Bob の追記がなくなる) | 自動 fetch のない環境の自分専用ブランチ |
--force-with-lease --force-if-includes |
上に加えて、取り込み済みか | 止まる (stale info) |
止まる (remote ref updated since checkout) |
rebase・amend 後の push 全般 |
強制 push が必要なときは、--force-with-lease --force-if-includes の組み合わせを既定にしておくと、ほかの人のコミットを残したまま進められます。 毎回打つのが長ければ、設定とエイリアスで短くできます。
git config --global push.useForceIfIncludes true # --force-with-lease に --force-if-includes を自動で付ける
git config --global alias.pushf "push --force-with-lease"
(push.useForceIfIncludes を設定して push が通ることは確認しました。エイリアスは登録できることのみ確認し、エイリアス経由の push は未実行です。)
強制 push で置き換えてしまった後の戻し方
置き換えた側(Alice)のリポジトリには、リモート追跡ブランチの履歴が残っています。
git reflog show origin/feature/login -4
4edfe88 refs/remotes/origin/feature/login@{0}: update by push
79dc9ae refs/remotes/origin/feature/login@{1}: fetch: fast-forward
cfbe716 refs/remotes/origin/feature/login@{2}: fetch: fast-forward
2c5f377 refs/remotes/origin/feature/login@{3}: update by push
(この出力は別の試行のもので、コミット ID は上のシナリオと異なります。)@{1} が強制 push の直前にリモートにあったコミットです。fetch 済みであれば、git push --force-with-lease origin <そのID>:feature/login のように指定して元の先端へ戻せます(戻す操作は未実行)。fetch していなかった場合は、そのコミットを持っている人(この例では Bob)にもう一度 push してもらうのが確実です。
サーバー側のルールで拒否されるとき(remote rejected)
! [rejected] は手元の Git が判断して止めたもの、! [remote rejected] はリモート側(サーバー)が拒否したものです。保護されたブランチへの直接 push を再現するため、練習用リモートに「main への push を断る」pre-receive フックを置いて試しました。
# remote.git/hooks/pre-receive(実行権限を付ける)
#!/bin/sh
while read old new ref; do
if [ "$ref" = "refs/heads/main" ]; then
echo "main は保護されています。プルリクエスト経由で反映してください。"
exit 1
fi
done
git switch main
echo m >> app.txt && git commit -am "mainを直接変更"
git push
remote: main は保護されています。プルリクエスト経由で反映してください。
To ../remote.git
! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to '../remote.git'
remote: で始まる行は、サーバーから届いたメッセージです。理由はここに書かれているので、まずこの行を読みます。
GitHub などのホスティングサービスでブランチ保護を有効にしている場合は、かっこの中が (protected branch hook declined) となり、remote: の行に「プルリクエストが必要」「レビューの承認が必要」といった理由が表示されます(この表示はサービスへの接続が必要なため今回は未実行で、一般に知られた文面です)。対処は共通で、作業ブランチを push してプルリクエストを作り、そこから反映します。
git switch -c fix/typo # main で作ったコミットを作業ブランチへ持っていく
git push -u origin fix/typo
git switch main
git reset --hard origin/main # 手元の main をリモートと同じ状態に戻す
(この持ち替え手順は未実行です。reset --hard は作業中の変更も元に戻すため、コミット済みであることを確認してから使います。)
サーバーの設定によっては、強制 push 自体を受け付けないこともあります。練習用リモートで receive.denyNonFastForwards を有効にして強制 push した結果です。
remote: error: denying non-fast-forward refs/heads/feature/login (you should pull first)
To ../remote.git
! [remote rejected] feature/login -> feature/login (non-fast-forward)
error: failed to push some refs to '../remote.git'
タグを push する
ブランチを push しても、タグは一緒には送られません。 タグは別に push します。
git tag v1.0.0 # 軽量タグ
git tag -a v1.1.0 -m "v1.1.0" # 注釈付きタグ
git push origin v1.0.0
To ../remote.git
* [new tag] v1.0.0 -> v1.0.0
残りのタグをまとめて送る前に、--dry-run で何が送られるかを確認できます。
git push --dry-run --tags
git push --tags
To ../remote.git
* [new tag] v1.1.0 -> v1.1.0
--dry-run と本番で同じ内容が表示されました(dry-run では実際には送られません)。
--follow-tags:コミットと注釈付きタグを一緒に送る
コミットを足して、注釈付きタグ v1.2.0 と軽量タグ light-tmp を付けてから実行しました。
git push --follow-tags
git ls-remote --tags origin
To ../remote.git
904aac6..35ff958 feature/search -> feature/search
* [new tag] v1.2.0 -> v1.2.0
e7cd654fd9e7f28dddd102e3955422b0447bc87d refs/tags/v1.0.0
b1072dfb476914202afa657ee515f17ac63747fd refs/tags/v1.1.0
e7cd654fd9e7f28dddd102e3955422b0447bc87d refs/tags/v1.1.0^{}
05bb8b320708256620592150edd45b64db1f4f13 refs/tags/v1.2.0
35ff95876ba0367aacf9a433fb54765735055922 refs/tags/v1.2.0^{}
--follow-tags は、push するコミットに付いた「注釈付きタグ」だけを一緒に送ります。 軽量タグの light-tmp はリモートに届いていません。一時的な目印(軽量タグ)を手元に置いたまま、リリース用のタグ(注釈付き)だけを共有したいときに便利です。
| コマンド | 送られるもの |
|---|---|
git push origin <タグ名> |
指定したタグ1つ |
git push --tags |
ローカルにあるすべてのタグ(軽量・注釈付きの両方) |
git push --follow-tags |
通常の push + 送るコミットに付いた注釈付きタグ |
git push origin --delete <タグ名> |
リモートのタグを削除 |
リモートブランチ・タグを削除する
git push origin --delete v1.0.0 # タグの削除
git push origin --delete remote-name # ブランチの削除
git push origin :feature/search # コロン記法(空のものを送る=削除)
To ../remote.git
- [deleted] v1.0.0
To ../remote.git
- [deleted] remote-name
To ../remote.git
- [deleted] feature/search
--delete(短縮形は -d)とコロン記法は同じ結果になります。意図が読み取りやすい --delete のほうをおすすめします。 存在しない名前を指定した場合は次のとおりです。
git push origin --delete nobranch
error: unable to delete 'nobranch': remote ref does not exist
error: failed to push some refs to '../remote.git'
リモートブランチを削除しても、手元のローカルブランチは残ります。 ローカル側は git branch -d <ブランチ名> で別に削除します。ほかの人のリポジトリに残っているリモート追跡ブランチは、各自が git fetch --prune を実行すると整理されます。
git push オプション早見表
| オプション | 短縮形 | 動き |
|---|---|---|
--set-upstream |
-u |
push と同時に upstream を登録する |
--force |
-f |
リモートの状態を確認せずに置き換える |
--force-with-lease |
― | リモートが最後に確認した状態のままなら置き換える |
--force-if-includes |
― | --force-with-lease と併用。取得済みの変更を取り込み済みか確認する |
--tags |
― | すべてのタグを送る |
--follow-tags |
― | 送るコミットに付いた注釈付きタグも送る |
--delete |
-d |
リモートのブランチ・タグを削除する |
--all |
― | すべてのローカルブランチを送る |
--dry-run |
-n |
実際には送らず、結果だけ表示する |
--atomic |
― | 複数のブランチ・タグを「すべて成功」か「すべて取りやめ」のどちらかにする |
--prune |
― | ローカルに対応するブランチがないリモートブランチを削除する |
--no-verify |
― | pre-push フックを実行しない |
--push-option=<文字列> |
-o |
サーバー側のフックへ文字列を渡す |
--verbose |
-v |
詳しい経過を表示する |
--porcelain |
― | スクリプトで扱いやすい形式で結果を出力する |
--atomic・--prune・--push-option の説明は公式ドキュメント(git-push)の記載に沿っています(動作は未実行)。--all --dry-run は実際に試し、送られるブランチの一覧と、rejected になるブランチが事前にわかることを確認しました。
git push --all --dry-run
To ../remote.git
* [new branch] feature/search -> feature/search
* [new branch] local-name -> local-name
! [rejected] feature/login -> feature/login (fetch first)
error: failed to push some refs to '../remote.git'
出力の記号の読み方
| 記号 | 意味 |
|---|---|
* [new branch] / * [new tag] |
リモートに新しく作られた |
abc1234..def5678 |
fast-forward で進んだ(通常の push) |
+ abc1234...def5678 (forced update) |
強制的に置き換えた |
- [deleted] |
削除した |
! [rejected] |
手元の Git が止めた |
! [remote rejected] |
リモート側が拒否した |
Everything up-to-date |
送るものがない |
push 前のチェックリスト
| 確認すること | コマンド |
|---|---|
| 今いるブランチと、リモートとの差 | git status -sb |
| これから送るコミットの一覧 | git log --oneline @{u}..HEAD |
| 送り先(upstream)の登録 | git branch -vv |
| 送る内容を事前に確認 | git push --dry-run |
| 強制 push の前に、リモートの最新状態を確認 | git fetch → git log --oneline HEAD..@{u} |
@{u} は「今いるブランチの upstream」を表す書き方です(この2つの git log コマンドは今回は未実行です)。強制 push の前に HEAD..@{u} で何か表示されたら、リモートに自分がまだ取り込んでいないコミットがあるという合図なので、先に取り込みます。
よくある質問
Q. git push と git push origin main は何が違いますか?
A. git push origin main は送り先と対象を明示する書き方で、どのブランチにいても「ローカルの main を origin の main へ」送ります。git push は今いるブランチを、登録済みの upstream へ送ります。upstream が未登録だと has no upstream branch と表示されるので、初回だけ -u を付けて登録します。
Q. rejected になったら、とりあえず --force を付ければよいですか?
A. まずは git pull --rebase でリモートの変更を取り込むのが基本です。rejected は「リモートに、手元にないコミットがある」という知らせなので、取り込めばそのまま push できます。強制 push が必要なのは、amend や rebase で push 済みのコミットを書き換えたときだけで、その場合も --force-with-lease --force-if-includes を使うと、ほかの人のコミットを残せます。
Q. -u は毎回付ける必要がありますか?
A. ブランチごとに最初の1回だけで十分です。登録後は git push だけで届きます。ブランチを作るたびに打つのを省きたい場合は、git config --global push.autoSetupRemote true を設定すると、upstream がないブランチでも git push だけで登録まで行われます。
Q. push したコミットを取り消したいときは?
A. 共有ブランチでは、git revert <コミットID> で「打ち消すコミット」を作って push する方法が向いています。履歴を書き換えないので、ほかの人の作業に影響しません。自分専用のブランチであれば、git reset で戻してから git push --force-with-lease --force-if-includes で反映する方法も選べます。
まとめ
- 初回は
git push -u origin <ブランチ名>で upstream を登録し、2回目以降はgit pushだけで送れる push.autoSetupRemote true(Git 2.37 以降)にすると、-uなしでも登録まで自動で行われる(fetch first)は未取得、(non-fast-forward)は未取り込み。どちらもgit pull --rebase→git pushで解決する--forceは確認なしで置き換える。2人作業のシナリオでは、相手のコミットがリモートからなくなった--force-with-leaseは fetch 前なら(stale info)で止まるが、fetch 後は通る。--force-if-includesを足すと、取り込み済みかどうかまで確認される! [remote rejected]はサーバー側のルール。remote:の行に書かれた理由を読み、作業ブランチとプルリクエストで反映する- タグはブランチと別に push する。
--follow-tagsは注釈付きタグだけを一緒に送り、削除はgit push origin --delete <名前>
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「git pushの使い方|-u・rejected・強制pushの対処」
株式会社RJCでは、git pushをはじめとするGitの共同作業の進め方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。