web-dev-qa-db-ja.com

gitブランチがプッシュされるのをブロックする

状況は次のとおりです。

Github.comにオープンソースアプリの公開リポジトリがあります。ただし、公開されない特定のコードを記述したいと思います(アプリケーションの商用バージョンで使用する可能性があります)。

同じリポジトリを使用できると思い、Gitリポジトリにプッシュしない「プライベート」ブランチを作成しました。

しかし、間違いは起こります。 gitがブランチをリモートサーバーにプッシュすることを禁止する方法はありますか?

この状況に対処するためのより良い方法があれば、もちろん私はどんな提案も歓迎します。

35
houbysoft

少しハックな解決策:GitHubに実際のブランチと同じ名前のダミーブランチを作成し、早送りマージにならないようにします。そうしないと、プッシュ操作は失敗します。

これが例です。

$ git clone [email protected]:user/repo.git
$ cd repo
$ git checkout -b secret
$ echo "This is just a dummy to prevent fast-forward merges" > dummy.txt
$ git add .
$ git commit -m "Dummy"
$ git Push Origin secret

ダミーブランチが設定されたので、ローカルで再作成して、GitHubのブランチから分岐させることができます。

$ git checkout master
$ git branch -D secret
$ git checkout -b secret
$ echo "This diverges from the GitHub branch" > new-stuff.txt
$ git add .
$ git commit -m "New stuff"

誤ってプッシュしようとすると、早送り以外のマージエラーで失敗します。

$ git Push Origin secret
To [email protected]:user/repo.git
! [rejected]        secret -> secret (non-fast forward)
error: failed to Push some refs to ‘[email protected]:user/repo.git’
27
hammar

dontpushthisというブランチを使用して、pre-Pushフックアプローチがどのように機能するかを次に示します。

このファイルを.git/hooks/pre-Pushとして作成します。

if [[ `grep 'dontpushthis'` ]]; then 
  echo "You really don't want to Push this branch. Aborting."
  exit 1
fi

これは、プッシュされている参照のリストが標準入力で渡されるために機能します。したがって、これはgit Push --allもキャッチします。

実行可能にします。

すべてのローカルリポジトリでこれを実行します。

そのブランチにプッシュしようとすると、次のように表示されます。

$ git checkout dontpushthis
$ git Push
You really don't want to Push this branch. Aborting.
error: failed to Push some refs to 'https://github.com/stevage/test.git'

明らかに、これは見た目と同じくらい単純で、「dontpushthis」という名前のブランチをプッシュすることを防ぐだけです。したがって、masterなどの重要なブランチに直接プッシュすることを避けようとしている場合に役立ちます。

機密情報の漏洩を防ぐという問題を解決しようとしているのなら、それだけでは不十分かもしれません。たとえば、dontpushthisからサブブランチを作成した場合、そのブランチは検出されません。より高度な検出が必要になります。たとえば、「dontpushthis」ブランチのコミットが現在のブランチに存在するかどうかを確認できます。

より安全なソリューション

もう一度質問を見ると、この場合のより良い解決策は次のようになると思います。

  1. 公開されているリポジトリを1つ持つ
  2. プライベートである新しい作業ディレクトリにそれを複製します
  3. その作業ディレクトリからリモート(git remote rm Origin)を削除します。
  4. 公開された変更をマージするには、git pull https://github.com/myproj/mypublicrepoを実行するだけです。

このように、プライベートリポジトリの作業ディレクトリには、プッシュできる場所がありません。あなたは本質的に、公開情報から非公開への一方向のバルブを持っていますが、戻ってはいけません。

35
Steve Bennett

@ steve-bennettからの.git/hooks/pre-Pushスクリプトの修正

    #!/usr/bin/bash

    branch_blocked=mine

    if grep -q "$branch_blocked"; then
        echo "Branch '$branch_blocked' is blocked by yourself." >&2
        exit 1
    fi
5
Lungang Fang

現在のgitバージョンで提供されているプレプッシュの例を単純に使用してみませんか?

アイデアは、Word PRIVATE:でプライベートブランチの最初のコミットのコミットメッセージを開始することです。

プレプッシュスクリプトを設定した後、プッシュごとに、プッシュされた参照のすべてのログのコミットメッセージをチェックします。 PRIVATE:で始まる場合、プッシュはブロックされます。

手順は次のとおりです。

  • .git/hooks/pre-Pushにファイルを作成します
  • 実行権を与える
  • その中の次のスクリプトを過ぎて

    #!/bin/sh
    
    remote="$1"
    url="$2"
    
    z40=0000000000000000000000000000000000000000
    
    IFS=' '
    while read local_ref local_sha remote_ref remote_sha
    do
            if [ "$local_sha" = $z40 ]
            then
                    # Handle delete
                    :
            else
                    if [ "$remote_sha" = $z40 ]
                    then
                            # New branch, examine all commits
                            range="$local_sha"
                    else
                            # Update to existing branch, examine new commits
                            range="$remote_sha..$local_sha"
                    fi
    
                    # Check for WIP commit
                    commit=`git rev-list -n 1 --grep '^PRIVATE:' "$range"`
                    if [ -n "$commit" ]
                    then
                            echo "Error: Found PRIVATE commit in $local_ref."
                            echo "The commit is in the range $range."
                            echo "NOT pushing!"
                            exit 1
                    fi
            fi
    done
    
    exit 0
    
    remote="$1"
    url="$2"
    

失敗の例

$ git Push Origin private/old-kalman-filter 
Found PRIVATE commit in refs/heads/myforbiddenbranch, the commit is in the range 
a15c7948676af80c95b96430e4240d53ff783455. NOT PUSHING!
error: failed to Push some refs to 'remote:/path/to/remote/repo'

ブランチを再びプッシュ可能にするには、フックを削除するか、コミットメッセージを変更して禁止されているWordを削除します。

このスクリプトは、remote_refをチェックすることにより、1つの禁止されたリモートのみを考慮するように変更できます。ただし、その場合は、このブランチの受信が許可されているすべてのリポジトリにこのフックをコピーすることを忘れないでください。

4
Aquadarius

リモートリポジトリに存在しないブランチを作成できます。

そうすれば、次のようになります。

git Push Origin

リモートリポジトリに存在するブランチのみをプッシュします。

また、ブランチを作成した後、.git/config(ローカルリポジトリディレクトリ内)ファイルを調べます。すべてのローカルブランチに異なるリモートリポジトリを割り当てることができることがわかります。このブランチを個別の(プライベート)リポジトリに割り当てることでこれを利用できますが、これはユニバーサルソリューションではありません(明示的に注文した場合、またはコマンドgit Push Originによって、ブランチをOriginリモートにプッシュできます)。

2
Tadeck

複数の解決策があります:

  1. 技術的ではありません。ブランチの商用ライセンスにライセンスを調整するだけです。
  2. フォークを含むプライベートリポジトリをgithubに作成します
  3. サーバーでgit-hookを作成します(githubではafaikは不可能です)
  4. git-Pushのラッパーを記述して、gitPushによるプッシュを防止します
2
Ulrich Dangel

GitHubを使用する場合は、GitHubにブランチと同じ名前のブランチを作成できます。コミットをプッシュする必要はありません。マスターなどから空のブランチを作成するだけです(GitHubインターフェースで、「ブランチ」ポップアップにブランチを入力してcreate branch <branch-name>をクリックすることで実行できます)。

次に、リポジトリのブランチ設定(https://github.com/<user>/<repo>/settings/branches/<branch-name>など)に移動し、ブランチのブランチ保護を有効にします。必ずすべてのチェックボックスをオンにしてください。特に、ブランチを直接プッシュすることを禁止する[レビューが必要]または[ステータス]チェックボックスをオンにしてください(プルリクエストからプッシュする必要があります)。管理者。

その場合、GitHubは、-fを使用していても、ブランチにプッシュすることを許可しません。次のようなメッセージが表示されます

$ git Push -f Origin private
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), 981 bytes | 981.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
remote: error: GH006: Protected branch update failed for refs/heads/private.
remote: error: At least 1 approving review is required by reviewers with write access.
To github.com:<user>/<repo>.git
 ! [remote rejected] private -> private (protected branch hook declined)
error: failed to Push some refs to '[email protected]:<user>/<repo>.git'
1
asmeurer