Подтвердить что ты не робот

Блокировать ветвь git от нажатия

Здесь ситуация:

У меня есть общий репозиторий для моего приложения с открытым исходным кодом на github.com. Однако теперь я хотел бы написать какой-то конкретный код, который не будет общедоступным (я могу использовать его в коммерческой версии моего приложения).

Я решил, что могу использовать один и тот же репозиторий, и я бы создал ветвь "private" в моем репозитории git, который я бы не нажал.

Но, ошибки случаются. Есть ли способ запретить git перетаскивать ветку на удаленные серверы?

Если есть лучший способ справиться с этой ситуацией, я, конечно же, буду приветствовать любые предложения.

4b9b3361

Ответ 1

Немного хакерское решение: сделайте фиктивную ветвь на GitHub с тем же именем, что и ваша настоящая ветка, и убедитесь, что это не будет быстрое слияние вперед. Таким образом, операция push не будет выполнена.

Вот пример.

$ 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’

Ответ 2

Здесь как работает подход к подходу pre-push, с ветвью, называемой dontpushthis.

Создайте этот файл как .git/hooks/pre-push:

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

Это работает, потому что список нажатий refs передается на стандартный ввод. Так что это также поймает 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", например, в текущей ветке.

Более безопасное решение

Глядя на вопрос снова, я думаю, что лучшим решением в этом случае будет:

  • Есть одно репо, которое является общедоступным.
  • Клонировать этот новый рабочий каталог, который является частным
  • Удалите удаленный (git remote rm origin) из этого рабочего каталога.
  • Чтобы слить общедоступные изменения, просто git pull https://github.com/myproj/mypublicrepo

Таким образом, в рабочем каталоге частного репо никогда не было нигде, где он мог бы нажать. У вас по существу есть односторонний клапан общественной информации для частного, но не обратно.

Ответ 3

Подсоединение .git/hooks/pre-push script от @steve-bennett

    #!/usr/bin/bash

    branch_blocked=mine

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

Ответ 4

Почему бы просто не использовать пример предварительного нажатия с текущей версией git?

Идея состоит в том, чтобы начать сообщение фиксации первого коммита вашей частной ветки со словом PRIVATE:.

После настройки предварительного нажатия script для каждого нажатия он проверяет сообщения фиксации всего журнала нажатых ссылок. Если они начинаются с PRIVATE:, нажатие будет заблокировано.

Вот шаги:

  • Создайте файл в .git/hooks/pre-push
  • Предоставить права выполнения
  • Прошел мимо script в нем

    #!/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'

Чтобы снова активировать ветвь, вы можете либо удалить крючок, либо, лучше, изменить сообщение фиксации, чтобы удалить запрещенное слово.

Этот script может быть изменен, чтобы рассматривать только один запрещенный пульт, проверяя remote_ref. Но в этом случае не забудьте скопировать этот крюк во все репозитории, разрешенные для получения этой ветки.

Ответ 5

Существует несколько решений:

  • Нетехнический, просто отредактируйте лицензию на коммерческую для вашей отрасли.
  • Создайте приватный репозиторий на github, который содержит вашу вилку
  • Сделайте git -hook на сервере (afaik невозможно с github)
  • Запишите обертку для git-push, чтобы предотвратить нажатие git push

Ответ 6

Вы можете создать ветвь, которая не существует в вашем удаленном репозитории.

Таким образом, если вы просто выполните:

git push origin

он будет нажимать только ветки, которые существуют в удаленном репозитории.

Также загляните в файл .git/config (в каталоге локального репозитория) после создания ветки - вы увидите, что каждый локальный филиал может иметь назначенный другой удаленный репозиторий. Вы можете воспользоваться этим, назначив эту ветвь отдельному (приватному) репозиторию, но это не универсальное решение (ветвь по-прежнему может быть нажата на исходный пульт, если явно указано, или командой git push origin).

Ответ 7

Если вы используете GitHub, вы можете создать ветку на GitHub с тем же именем, что и ваша ветка. Нет необходимости выдвигать какие-либо коммиты на него, просто создайте пустую ветку вне master или чего-либо еще (вы можете сделать это в интерфейсе GitHub, набрав ветку во всплывающем окне "branch" и нажав 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'