Помилка Git push '[віддалено відхилено] master -> master (гілка зараз перевірена)'


961

Вчора я розмістив запитання про те, як клонувати сховище Git з однієї зі своїх машин на іншу. Як я можу "git clone" з іншої машини? .

Зараз я можу успішно клонувати репозиторій Git з мого джерела (192.168.1.2) до мого місця призначення (192.168.1.1).

Але коли я змінив файл, a git commit -a -m "test"і a git push, я отримую цю помилку за призначенням (192.168.1.1):

git push                                                
hap@192.168.1.2's password: 
Counting objects: 21, done.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (11/11), 1010 bytes, done.
Total 11 (delta 9), reused 0 (delta 0)
error: refusing to update checked out branch: refs/heads/master
error: By default, updating the current branch in a non-bare repository
error: is denied, because it will make the index and work tree inconsistent
error: with what you pushed, and will require 'git reset --hard' to match
error: the work tree to HEAD.
error: 
error: You can set 'receive.denyCurrentBranch' configuration variable to
error: 'ignore' or 'warn' in the remote repository to allow pushing into
error: its current branch; however, this is not recommended unless you
error: arranged to update its work tree to match what you pushed in some
error: other way.
error: 
error: To squelch this message and still keep the default behaviour, set
error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To git+ssh://hap@192.168.1.2/media/LINUXDATA/working
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'git+ssh://hap@192.168.1.2/media/LINUXDATA/working'

Я використовую дві різні версії Git (1,7 на віддаленому та 1,5 на локальній машині). Це можлива причина?


5
Чи може будь-який старожил змінити прийняту відповідь на stackoverflow.com/a/9283833/397872 та перемістити потік до архіву чи щось таке? Або змінити право власності чи що завгодно?
ришта

9
Ви на самому справі тепер є безпечний спосіб підштовхнути до НЕ голу репо з Git 2.3.0 (лютий 2015) і git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309
VonC

Ось нове посилання книги, про яке згадував @stigi
Абделіла Ель-Айсауї


Але я розумію, чому і як це працює? Це працює, так, але це все.
Тілак Мадді

Відповіді:


1149

Ви можете просто перетворити віддалене сховище в оголене сховище (в голому сховищі немає робочої копії - папка містить лише фактичні дані сховища).

Виконайте таку команду у папці віддаленого сховища:

git config --bool core.bare true

Потім видаліть усі файли, крім .gitцієї папки. І тоді ви зможете виконуватись git pushу віддаленому сховищі без будь-яких помилок.


4
Дякую. Мені теж це було потрібно. Я слідкував за підручником з підмодулів із книги Git Community Book і потрапив у цю блоку.
Шики

6
Я не був впевнений, чи ти мав на увазі видалити файли на сервері чи на клієнті ... тому я нічого не видалив, і проблема зникає після того, як це зробити git config --bool core.bare true. Чи є певна причина, яку деякі файли потрібно видалити? Якщо так, чи можете ви бути більш точними щодо того, що потрібно видалити?
Брайан Ванденберг

24
Це найкраща можлива відповідь, і ніхто більше не надав її в отвір Interwebs. Я думаю, що всі ми гуглили одне і те ж повідомлення про помилку, і всі ми були надзвичайно раді прочитати це.
Себастьян Гріньолі

40
Хоча набрав багато голосів, я не думаю, що це справді адекватна відповідь на це конкретне питання. Інструкція користувача, як чисто створити голий репо, буде вдвічі поганою, але що робити, якщо файли потрібно перевіряти, наприклад, коли це сховище, з яким користувач працює на двох комп’ютерах?
Ніде людина

9
Зміна вихідного репо на голе є надмірним. Все, що вам потрібно зробити - це перейти до нової гілки у вихідному репо, як зазначає @Robert: stackoverflow.com/a/2933656/402949 .
Дан Соловий

707

У мене просто була така ж помилка, коли я почав вивчати Git . Деякі з інших відповідей явно не для когось нового в Git!

(Я буду використовувати нетехнічні терміни, щоб донести ідею.) У будь-якому випадку, це те, що у вас є два сховища, одне - це оригінал, який ви вперше зробили, а інший - те, що ви тільки що зробили.

Зараз ви перебуваєте у вашому робочому сховищі та використовуєте гілку "master". Але також трапляється, що ви "увійшли" у своєму первісному сховищі до того ж "головного" відділення. Оскільки ви "увійшли" в оригіналі, Git побоюється, що ви можете зіпсуватись, тому що ви можете працювати над оригіналом і накручувати речі. Тож вам потрібно повернутися до оригінального сховища та зробити "git checkout sometherbranch", і тепер ви можете без проблем.

Я сподіваюся, що це допомагає.


76
+1 Набагато корисніше, дякую Роберту. Я не мав сенсу перетворюватися на оголене репо в моєму випадку. Просто потрібно «деактивувати» гілку, на яку ви намагаєтесь натиснути. Має сенс.
Ерік Мюйзер

32
@ FMaz008: просто створіть фіктивну гілку (git checkout -b манекен)
Dror Cohen

14
Людина, це набагато краще, ніж більшість проголосованих відповідей :) Дякую. Хоча інша відповідь також
підкреслює

102
Просто щоб зробити це більш ясним, в репо , що це мета натиску: git checkout -b tmp. Тоді в джерелі репо: git push. Потім повернемося в ціль (необов’язково):git checkout master; git branch -d tmp
Харі Карам Сінгх

18
Коментар Харі - найпростіший рецепт. Я просто мушу сказати, що хоча git може бути чудовим у багатьох відношеннях, виходячи з svn або, мабуть, будь-яких інших rvs, ця вся справа надзвичайно неінтуїтивна.
БезумовноВстановітьMonica

128

Повідомлення про помилку описує те, що сталося. Більш сучасні версії Git відмовляються від оновлення гілки за допомогою натискання, якщо ця гілка перевірена.

Найпростіший спосіб роботи між двома неочищеними сховищами - це або

  1. завжди оновлюйте сховища шляхом витягування (або отримання та злиття) або, якщо вам потрібно,

  2. натиснувши на окрему гілку (гілку імпорту), а потім об'єднавши її в головну гілку на віддаленій машині.

Причиною цього обмеження є те, що push-операція працює лише у віддаленому сховищі Git, вона не має доступу до індексу та робочого дерева. Отже, якщо це дозволено, натискання на відмінену гілку змінило б, HEAD щоб воно не відповідало індексу та робочому дереву у віддаленому сховищі.

Це дозволило б дуже легко випадково здійснити зміну, яка скасовує всі натиснуті зміни, а також дуже важко розрізнити будь-які локальні зміни, які не були здійснені, та відмінності між новим HEAD, індексним та робочим деревом, які були викликані рухом поштовху HEAD.


1
Дякую. Тож як я можу виправити свою проблему? У своєму вікні 192 я зробив '$ cd (каталог проектів) $ git init $ (додати деякі файли) $ git add.' а потім у своєму вікні 191 я зробив "git clone" та редагував деякі файли, а потім намагався "git push".
hap497

16
Що ж, я описав можливості у своїй відповіді. Або ви можете перейти до вікна 192 та отримати з вікна 191 (ви можете додати поле 191 як названий дистанційний - подивіться git remote add box191 <191url>), або ви можете натиснути з поля 191 на іншу назву гілки (наприклад git push origin master:refs/heads/upload), потім до вікна 192 і злитися (наприклад git merge upload).
CB Bailey

3
Насправді тепер у вас є безпечний спосіб перейти на нечисте репо з Git 2.3.0 (лютий 2015) та git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309 : варіант 2 вам більше не потрібен.
VonC

122

Підсумок

Ви не можете натиснути на одну перевірену гілку сховища, тому що вона зіпсується з користувачем цього сховища таким чином, який, швидше за все, закінчиться втратою даних та історії . Але ви можете перейти до будь-якої іншої гілки того ж сховища.

Оскільки в голих сховищах ніколи не перевіряється жодна гілка, ви завжди можете перейти до будь-якої гілки голого сховища.

Існує кілька рішень, залежно від ваших потреб.

Рішення 1: Використовуйте голий репортаж

Як запропоновано, якщо на одній машині робочий каталог вам не потрібен, ви можете перейти до голого сховища. Щоб уникнути возитися з сховищем, ви можете просто його клонувати:

machine1$ cd ..
machine1$ mv repo repo.old
machine1$ git clone --bare repo.old repo

Тепер ви можете натиснути все, що ви хочете, на ту ж адресу, що і раніше.

Рішення 2: Натисніть на відділення без перевірки

Але якщо вам потрібно перевірити код на пульті <remote>, то ви можете використовувати спеціальну гілку для натискання. Скажімо, у вашому локальному сховищі ви зателефонували на ваш дистанційний originі ви перебуваєте у майстрі відділення. Тоді ви могли б зробити

machine2$ git push origin master:master+machine2

Тоді вам потрібно об’єднати його, коли ви знаходитесь у originвіддаленому репо:

machine1$ git merge master+machine2

Розтин проблеми

Коли філія перевірена, команда фіксації додасть нову команду з головою поточної гілки як її батьківською і перемістить голову гілки на цю нову команду.

Тому

A ← B
    ↑
[HEAD,branch1]

стає

A ← B ← C
        ↑
    [HEAD,branch1]

Але якби хтось міг просунутися до цієї гілки між ними, користувач отримав би себе в тому, що git викликає відключений головний режим:

A ← B ← X
    ↑   ↑
[HEAD] [branch1]

Тепер користувач більше не перебуває у відділенні1, не вимагаючи прямо перевірити іншу гілку. Гірше, що користувач зараз знаходиться поза будь-яким відділенням , і будь-яка нова комісія буде просто звисати :

      [HEAD]
        ↓
        C
      ↙
A ← B ← X
        ↑
       [branch1]

Гіпотетично, якщо в цей момент користувач перевіряє іншу гілку, то ця звисаюча фіксація стає чесною грою для збирача сміття Git .


3
Одне технічне виправлення "аутопсії": git насправді не від'єднується HEADу сховищі, що пересувається. HEADвсе ще вказуватиме на гілку, а гілка в свою чергу вказуватиме на нове (-те) переміщення (-і); але робочий каталог та область індексів / інсценізацій будуть незміненими. Той, хто працює над сховищем, що пересувається, тепер повинен наполегливо попрацювати, щоб відновити наслідки натискання: з’ясуйте, чи є якісь зміни для їх збереження, і якщо так ретельно домовитися про їх збереження.
торек

Щоб додати додаткову інформацію до своєї відповіді, є дуже мало причин, чому ви хочете, щоб віддалене сховище, яке люди намагаються зробити не голим, тому використання голого сховища є найкращим рішенням.

2
Насправді я виявив багато ситуацій, коли мені потрібно перейти до неоголеного сховища, і я досить багато використовую рішення 2. Крім того, гілка, куди я натискаю на неоголене сховище, жодним чином не є тимчасовою гілкою, вона виконує аналогічну мету, як відділення віддаленого відстеження.
Ніде людина

Я створив папку GIT на своєму сервері, де будуть розміщені ВСІ сховища, створені багатьма користувачами за допомогою SourceTree. Я створив masterсховища у своєму локальному ПК. Я додав remotesпапку до сервера і намагаюся підштовхнути своє сховище до сервера, щоб інший користувач міг витягнути / взяти його для роботи. Я отримую таку помилку: ! [remote rejected] master -> master (branch is currently checked out)як я можу це перевірити?
SearchForKnowledge

1
@SearchForKnowledge, ти розумієш, що ти задаєш саме те питання, на яке я відповідаю ?!
Ніде людина

65

Ви можете обійти це "обмеження", відредагувавши .git/configна сервері призначення. Додайте наступне, щоб дозволити переміщення сховища git, навіть якщо воно "перевірено":

[receive]
denyCurrentBranch = warn

або

[receive]
denyCurrentBranch = false

Перший дозволить натиснути, попередивши про можливість зіпсувати гілку, тоді як другий просто тихо дозволить.

Це можна використовувати для "розгортання" коду на сервері, який не призначений для редагування. Це не найкращий підхід, але швидкий для розгортання коду.


7
Використовуючи це для "розгортання" коду на сервері, не вийде. Навіть якщо ви вимкнете попередження, щоб ви могли натиснути на перевірену гілку, робоча копія НІКОЛИ не оновлюється під час натискання.
Arrowmaster

10
Я використовую вищезазначений метод з cd .. && git reset --hardгачком після отримання після розгортання. Хакіш, але працює.
jholster

9
версія командного рядка останньої будеgit config receive.denyCurrentBranch warn
Андре Хольцнер

4
Це має бути прийнятою відповіддю. Деякі з нас знають, що ми робимо, і не є початківцями Git. Це відповідь для тих людей.
Qix - МОНІКА ПОМИЛИЛА

2
Ха, але це питання не було задано тими людьми.
Ніде людина

46

git config --local receive.denyCurrentBranch updateInstead

https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155

Використовуйте це у сховищі сервера, і він також оновлює робоче дерево, якщо не буде перезаписано незавершене перезапис.

Він був доданий у Git 2.3, як згадував VonC у коментарях.

Я склав Git 2.3 і спробував його. Використання зразка:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master

cd ../server
ls

Вихід:

a
b

Так, bштовхнули!


@ VonC дякую! Це моя одержимість мінімальними прикладами на роботі :-)
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Чи є в цьому проблеми із внесенням змін, які не є актуальними для сервера?
акозі

@akozi Я не впевнений, що ви маєте на увазі, якщо ви скористаєтесь локально перед тим, як потягнути, він буде вести себе як традиційний --bareклон, я думаю: --forceйого потрібно натиснути, і це змусить вас "втратити" зобов'язання на пульті.
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

1
@CiroSantilli 新疆 改造 中心 六四 事件 法轮功 Більше не хвилюйся. Я переглянув значення варіантів. Я думав, що оновленняInstead було синонімом сили.
akozi

updateInstead більше не є дійсним значенням для
prima.denyCurrentBranch

41

Мені подобається ідея збереження корисного сховища у віддаленому вікні, але замість фіктивного відділення я люблю використовувати:

git checkout --detach

Це здається дуже новою особливістю Git - я використовую git версії 1.7.7.4.


8
А потім, натиснувши свої зміни, ви можете використовувати: git checkout masterщоб повернутися до ведучої гілки. Лише тоді застосовуються ваші зміни.
МАЗДАК

30

У мене було те саме питання. Для мене я використовую Git push для переміщення коду на свої сервери. Я ніколи не змінюю код на стороні сервера, тому це безпечно.

У сховищі ви натискаєте набрати:

git config receive.denyCurrentBranch ignore

Це дозволить вам змінити сховище, поки це робоча копія.

Після запуску кнопки Git перейдіть до віддаленої машини та введіть це:

git checkout -f

Це призведе до відображення змін, які ви натиснули, у робочій копії віддаленої машини.

Зауважте, це не завжди безпечно, якщо ви внесете зміни до робочої копії, на яку ви наполягаєте.


дякую журнал, я зливаю вам пропозицію denyCurrentBranchі поміщаю git checkout -fвсередину hooksпапки на кшталт @ jack-senechal, розміщені тут
Éderson T. Szlachta

Чи є спосіб змусити файли з’являтися у віддаленому сховищі, не переходячи до нього та виконуючи цю команду? А саме за командою від місцевих?
Рой

24

Ви можете відтворити своє сховище сервера і перейти від вашого локального майстра відділення до майстра сервера.

На віддаленому сервері:

mkdir myrepo.git
cd myrepo.git
git init --bare

Гаразд, від вашого місцевого відділення:

git push origin master:master

3
Дякую, це було рішенням для мене, оскільки я пропустив '--bare' на віддаленому сервері. Схоже, що відповіді на це питання залежать від того, використовуєте ви віддалений сервер репо як робочий каталог, чи ні, і для подальшого випадку це правильна відповідь.
Кас

2
Я не розумію: СІ намагався створити і клонувати оголене репо, але клон нічого не завантажив і нічого не завантажив, так що це не працює ... :-) Я читав підручники про голі репо, але вони кажуть, що голе репо не містить файлів ... Це точно не те, що я шукаю ...
inf3rno

22

Що ви, мабуть, зробили для цього:

Такі речі трапляються, коли ви хочете вирвати трохи програми. Ви збираєтесь змінити щось, що вже працювало, тому ви додали свій заклинання тривалої непереборності 3 рівня:

machine1:~/proj1> git init

і ви починаєте додавати / здійснювати. Але потім проект починає активізуватися, і ви хочете працювати над ним на іншому комп’ютері (наприклад, на домашньому ПК або ноутбуці), тож ви робите щось на зразок

machine2:~> git clone ssh://machine1/~/proj1

і він клонується, і все виглядає добре, і тому ви працюєте над своїм кодом з машини2.

Тоді ... ви намагаєтеся відсунути свої зобов'язання від machine2, і ви отримаєте попереджувальне повідомлення в заголовку.

Причина цього повідомлення полягає в тому, що git repo, з якого ви витягли, було начебто призначене для використання саме для цієї папки на машині1. Ви можете клонувати з нього просто чудово, але натискання може спричинити проблеми. "Правильний" спосіб управління кодом у двох різних місцях - це "голе" репо, як було запропоновано. Гола репо не розроблена для того, щоб виконувати будь-яку роботу в ній, вона покликана координувати комісії з різних джерел. Ось чому найвища відповідь пропонує видалити всі файли / папки, крім папки .git після вас git config --bool core.bare true.

Уточнення найкращої відповіді: Багато коментарів до цієї відповіді говорять про щось на кшталт "Я не видалив не-.git файли з машини1, і я все ще зміг зробити з машини2". Це вірно. Однак ці файли повністю "розлучені" з git repo. Спробуйте спробувати git statusтам, і вам слід побачити щось на кшталт "фатально: цю операцію потрібно запустити в робочому дереві". Отже, пропозиція видалити файли не є такою, що фіксація з machine2 буде працювати ; це так, що ви не заплутаєтесь і не думаєте, що git все ще відстежує ці файли. Але видалення файлів є проблемою, якщо ви все ще хочете працювати над файлами на machine1, чи не так?

Отже, що ви насправді повинні робити?

Залежить від того, скільки ви плануєте продовжувати працювати на machine1 та machine2 ...

Якщо ви закінчили розробку з machine1 і перенесли всю свою розробку на machine2 ... просто зробіть те, що пропонує найкраща відповідь: git config --bool core.bare trueа потім, при необхідності, видаліть усі файли / папки, крім .git, із цієї папки, оскільки вони Ви не будете відслідковуватися і, ймовірно, можуть викликати плутанину.

Якщо ваша робота над машиною2 була лише разовою справою, і вам не потрібно продовжувати там розробляти ... тоді не поспішайте робити оголене репо; просто ftp / rsync / scp / тощо. ваші файли з машини * 2 * поверх файлів на машині * 1 *, виконайте / натисніть з машини * 1 *, а потім видаліть файли з машини * 2 *. Інші пропонують створити філію, але я думаю, це трохи безладно, якщо ви просто хочете одноразово об'єднати якусь розробку з іншої машини.

Якщо вам потрібно продовжувати розробку як на машині1, так і на машині2 ..., тоді вам потрібно налаштувати все належним чином. Вам потрібно перетворити репо в голий, тоді вам потрібно зробити клон цього на machine1, щоб ви могли працювати . Мабуть, найшвидший спосіб це зробити - це зробити

machine1:~/proj1> git config --bool core.bare true
machine1:~/proj1> mv .git/ ../proj1.git
machine1:~/proj1> cd ..
machine1:~> rm -rf proj1
machine1:~> git clone proj1.git
machine1:~> cd proj1

Дуже важливо: оскільки ви перемістили розташування репо з proj1 в proj1.git, вам потрібно оновити це у файлі .git / config на machine2 . Після цього ви можете здійснити свої зміни з машини2. Нарешті, я намагаюся тримати мої голі репозиції в центральному місці, подалі від моїх робочих дерев (тобто не ставте 'proj1.git' у ту саму батьківську папку, що і 'proj1'). Раджу зробити так само, але я хотів, щоб кроки вище були максимально простими.


Дуже детально і корисно. Моя справа була останньою, і ваші вказівки спрацювали як шарм.
pojda

Я у випадку 3, і я зробив щось трохи інше: mk git-сервер; mv. Я зберігаю голу головну копію, яка буде подібна до звичайної на GH або іншому HTTP-сервері, і я продовжуватиму використовувати push / pull на обох машинах.
zakmck

18

За допомогою декількох кроків налаштування ви можете легко розгорнути зміни на своєму веб-сайті за допомогою одноланкового типу

git push production

Що приємно і просто, і вам не потрібно входити на віддалений сервер і робити щось або щось таке. Зверніть увагу, що це буде найкращим чином, якщо ви не використовуєте замовлення виробництва як робочу гілку! (ОП працювала в дещо іншому контексті, і я думаю, що рішення @Robert Gould вирішило це добре. Це рішення є більш підходящим для розгортання на віддалений сервер.)

Спочатку вам потрібно налаштувати голий сховище десь на вашому сервері, поза вашою веб-коренею.

mkdir mywebsite.git
cd mywebsite.git
git init --bare

Потім створіть файл hooks/post-receive:

#!/bin/sh
GIT_WORK_TREE=/path/to/webroot/of/mywebsite git checkout -f

І зробіть файл виконуваним:

chmod +x hooks/post-receive

На вашій локальній машині

git remote add production git@myserver.com:mywebsite.git
git push production +master:refs/heads/master

Все готово! Тепер у майбутньому ви можете використовуватиgit push production для розгортання змін!

Заслуга за це рішення посилається на http://sebduggan.com/blog/deploy-your-website-changes-using-git/ . Подивіться там, щоб отримати більш детальне пояснення того, що відбувається.


Ваша пропозиція мені дуже допомогла, але я не скористався bare, я слідую за цим і зливаюся з hooks(що ви запропонували) і прекрасно працював.
Éderson T. Szlachta

11

Вам слід лише натиснути на оголене сховище. Голий сховище - це сховище, яке не має перевірених гілок. Якщо ви мали б CD в голий каталог сховища, ви побачили б лише вміст .git каталогу.


9
Немає нічого поганого в тому, щоб натиснути на неперевірену гілку в неоголеному сховищі. Це ідеально правильний спосіб роботи.
CB Bailey

Досить справедливо, це працювало б. Але це не те, що робить користувач.
RibaldEddie

13
Справа не в тому, що він не використовує оголене сховище, яке є «неправильним»; це той факт, що він підштовхує до перевіреної гілки. Немає жодних доказів того, що він має або бажає окремого голого сховища, тому ваше твердое твердження про те, що він повинен лише підштовхуватися до неоголеного сховища, не надає запитувачу всіх варіантів; один з яких може легше вирішити його безпосередню проблему.
CB Bailey

10

У вас є 3 варіанти

  1. Потягніть і натисніть знову:

    git pull; git push
    
  2. Натисніть на іншу галузь:

    git push origin master:foo
    

    і об'єднати його на пульті дистанційного керування (або gitчи висувної запитом )

    git merge foo
    
  3. Примушуйте це (не рекомендується, якщо ви навмисно не змінили зобов’язання через rebase):

    git push origin master -f
    

    Якщо все - таки відмовився, відключити denyCurrentBranch на віддаленому сховище:

    git config receive.denyCurrentBranch ignore
    

Варіант 2 працює для мене. віддалений git init локальний git push origin master: відділення віддалений git merge
Jacky Chong

7

Насправді встановити пульт дистанційного керування для перевіреної гілки достатньо. Після того, як ви перевірили пульт в іншій гілці, ви можете натиснути.


7

Перевірте свій .git/configпроект призначення:

$ cat .git/config 
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[receive]
    denyCurrentBranch = updateInstead

Якщо значення core. barefalse, ви можете встановити його як true:

$ git config core.bare true

а потім у локальному натиску на віддалений:

git push remote_repo   // suppose the destination repo is remote_repo

це вдасться, у remote_repo ви можете перевірити версію git.

$ git log -1
commit 0623b1b900ef7331b9184722a5381bbdd2d935ba
Author: aircraft < aircraft_xxx@126.com>
Date:   Thu May 17 21:54:37 2018 +0800

і тепер ви не можете використовувати git у своїй "робочій області":

$ git status
fatal: This operation must be run in a work tree

ви повинні встановити bare.bareзначення false.

$ git config core.bare false

5

У мене була така ж проблема з використанням Git для синхронізації сховищ на моєму телефоні та ноутбуці Android. Для мене рішення було зробити тягнення замість натискання, як запропонував @CharlesBailey.

git push origin master в репозиторії Android не вдається мені з тими самими повідомленнями про помилки, які отримали @ hap497 через натискання на необмежену реєстрацію сховища + робоча копія.

git pull droid masterв репозиторії ноутбука і робоча копія для мене працює. Звичайно, потрібно попередньо запустити щось подібне git remote add droid /media/KINGSTON4GB/notes_repo/.


4

Старіші версії Git використовувались, щоб дозволити натискання на перевірену в даний час гілку незаголеного сховища.

Виявляється, це було жахливо заплутано. Тож вони додали попереджуване повідомлення, яке ви бачите, яке також страшенно заплутано.

Якщо перший сховище просто виступає в якості сервера, тоді перетворите його в голое сховище, як рекомендують інші відповіді, і виконайте його.

Якщо вам потрібно мати спільну гілку між двома репостами, які обидва використовуються, ви можете досягти цього за допомогою наступного налаштування

Repo1 - буде виконувати роль сервера, а також використовуватиметься для розробки

Repo2 - буде лише для розвитку

Настройте Repo1 наступним чином

Створіть відділення для спільної роботи.

git branch shared_branch

Для безпеки ви також повинні створити $ (REPO) .git / hooks / update, який відхиляє будь-які зміни, ніж те, що є спільним_branch, тому що ви не хочете, щоб люди спілкувалися з вашими приватними відділеннями.

repo1/.git/hooks  (GIT_DIR!)$ cat update
#!/bin/sh
refname="$1"
oldrev="$2"
newrev="$3"

if [ "${refname}" != "refs/heads/shared_branch" ]
then
   echo "You can only push changes to shared_branch, you cannot push to ${refname}"
   exit 1
fi

Тепер створіть локальну гілку в repo1, де ви будете виконувати свою фактичну роботу.

git checkout -b my_work --track shared_branch
Branch my_work set up to track local branch shared_branch.
Switched to a new branch 'my_work'

(може знадобитися для git config --global push.default upstreamтого, щобgit push щоб працювати)

Тепер ви можете створити репо2 за допомогою

git clone path/to/repo1 repo2 
git checkout shared_branch 

На цьому етапі у вас є і налаштування repo1, і repo2, щоб працювати на локальних гілках, які натискають і тягнуть з себе shared_branchв repo1, не потрібно турбуватися про це повідомлення про помилку чи не виводити робочий каталог з синхронізації в repo1. Який би нормальний робочий процес ви не використовували, він повинен працювати.


3

Гаразд, якщо ви хочете мати звичайний віддалений сховище, тоді створіть додаткову гілку та перевірте її. Натисніть на одну гілку (яка не перевірена) та з'єднайте її з тією, яка наразі є активною пізніше після натискання з локального.

Наприклад, на віддаленому сервері:

git branch dev
git checkout dev

У локальному налаштуванні:

git push 

На віддаленому сервері:

git merge dev

2

Ось один тест, який ви можете зробити, щоб побачити, як працюють bareсерверні речі:

Уявіть, що у вас є робоча станція та сервер із живим веб-сайтом, на якому розміщено веб-сайт, і ви хочете час від часу оновлювати цей сайт (це стосується також ситуації, коли два розробники надсилають свою роботу туди-сюди через голого посередника).

Ініціалізація

Створіть на своєму локальному комп’ютері деякий каталог та cdвиконайте ці команди:

# initialization
git init --bare server/.git
git clone server content
git clone server local
  1. Спочатку ви створюєте голий server каталог (помітьте .git в кінці). Цей каталог буде служити контейнером лише для ваших файлів сховища.
  2. Потім клонуйте ваше сховище сервера до новоствореного contentкаталогу. Це ваш довідковий каталог / виробництво, яке обслуговуватиме ваше серверне програмне забезпечення.
  3. Перші два каталоги знаходяться на вашому сервері, третій - локальний каталог на вашій робочій станції.

Робочий процес

Тепер ось основний робочий процес:

  1. Увійдіть у localкаталог, створіть деякі файли та скопіюйте їх. Нарешті натисніть їх на сервер:

    # create crazy stuff
    git commit -av
    git push origin master
    
  2. Тепер введіть contentкаталог і оновіть вміст сервера:

    git pull
    
  3. Повторіть 1-2. Тут contentможе бути інший розробник, який теж може натиснути на сервер, і localяк ви можете витягнути з нього.


2

Використовуючи це, щоб підштовхнути його до віддаленої гілки вище за течією, вирішив цю проблему для мене:

git push <remote> master:origin/master

Пульт не мав доступу до репо за течією, тому це був хороший спосіб отримати останні зміни в цей пульт


1
Більш загально (оскільки це чистий ефект команди), використовуючи git push <remote> master:newbranch. Ідея полягає в тому, що ви натискаєте нову гілку на пульт, в яку потім можна об'єднатись. Таким чином ви уникнете будь-яких проблем з неузгодженістю, згаданих у повідомленні про помилку.
Глина

1

Мені довелося повторно запуститись git --initу існуючому голому сховищі, і це створило .gitкаталог всередині голого дерева сховища - я зрозумів, що після введення git statusтам. Я це видалив і знову все було добре :)

(Усі ці відповіді чудові, але в моєму випадку це було щось зовсім інше (наскільки я бачу), як описано.)


1

Я впевнений, що більшість людей, які переглядають це питання, зупиняться на перших двох величезних відповідях, але я все ж хотів би запропонувати своє рішення.

У мене виникло налаштування веб-проекту Eclipse + EGit при зустрічі з описаною помилкою. Що мені допомогло - просто скористатися додатком GitHub, який, здавалося, магічно вирішив проблему. Хоча EGit завжди відмовлятиметься від натискання, настільний додаток GitHub просто знизає плечима і підштовхне мої зміни. Можливо, це справляється з ситуацією з кількома входами більш витончено.


1

Стаття, яку я виявив, що може бути корисною іншим, - це Git за 5 хвилин .

У мене був проект Xcode під керуванням версії Git, який я хотів перейти до віртуальної розподіленої Ethernet (VDE), що є у мене в DC. VDE запускає Centos 5.

Жодна із статей, які я читала про Git, не розповідала про голі сховища. Все це звучало так просто, поки я не спробував те, що, на мою думку, повинно бути легким від SVN фону.

Тут запропоновано зробити віддалений сховище оголеним. Ще краще для моїх вимог було клонувати проект Xcodeprojectname.git скопіювати його на віддалений сервер; потім натискання магічно спрацювали. Наступним кроком буде отримання Xcode, щоб просуватись без помилок стосовно комітетів, але поки я все добре, роблю це з терміналу.

Тому:

cd /tmp (or another other directory on your system)<br/>
git clone --bare /xcode-project-directory projectname.git<br/>
scp -r projectname.git sshusername@remotehost.com:repos/<br/>

Щоб натиснути зміни з вашого проекту Xcode після того, як ви виконали Xcode:

cd /xcode-project-directory<br/>
git push sshusername@remotehost.com:repos/projectname.git<br/>

Я впевнений, що є більш складний спосіб робити вищезазначене, але як мінімум це працює. Ось так, щоб все було зрозуміло, ось декілька роз’яснень: /xcode-project-directoryчи каталог, в якому зберігається ваш проект xcode. Це, мабуть/Users/Your_Name/Documents/Project_Name . ім'я проекту - це буквально назва проекту, але назвати його може будь-що. Гіт не хвилює, ти будеш.

Для використання scp вам потрібно мати обліковий запис користувача на віддаленому сервері, на якому дозволений доступ SSH . Усі, хто працює з власним сервером, матимуть це. Якщо ви використовуєте спільний хостинг або подібне, вам може не пощастить.

remotehost.com- ім'я віддаленого хоста. Ви можете так само легко використовувати його IP-адресу. Просто для подальшої ясності я використовую Gitosis на віддаленому хості з ключами SSH, тому мені не запитують паролі при натисканні. Стаття Хостинг репозиторіїв Git, простий (та безпечний) спосіб розповість, як налаштувати все це.


1

Найкращий спосіб зробити це:

mkdir ..../remote
cd ..../remote
git clone --bare .../currentrepo/

Це дозволить клонувати сховище, але воно не буде робити жодних робочих копій .../remote. Якщо ви подивитесь на пульт, ви побачите один створений каталог, який називається currentrepo.git, і це, мабуть, те, що ви хочете.

Потім з вашого локального сховища Git:

git remote add remoterepo ..../remote/currentrepo.git

Після внесення змін ви можете:

git push remoterepo master

1

Я щойно зіткнувся з цією проблемою із сховищем git розгортання на Heroku .

Я не знаю, чому у Heroku є нечисте сховище на їхньому боці, але як вирішення проблеми я зміг скинути віддалене сховище та перезавантажити його.

Ви не повинні використовувати копію вашого сховища Heroku як єдине сховище git для співпраці, але на всякий випадок я скажу чітко: Не робіть цього, якщо ви впевнені, що у вас повністю зберігається повна копія вашого сховища де-небудь, крім Хероку. Якщо зробити скидання, буде видалено вміст сховища.

Щоб скинути:

  1. Встановіть пояс інструмента Heroku (який містить клієнт командного рядка), якщо ви ще цього не зробили.
  2. Встановіть плагін heroku-repo, якщо ви ще цього не зробили.

    heroku plugins:install https://github.com/heroku/heroku-repo.git
    
  3. Зробіть скидання, яке видаляє сховище та створить нове, порожнє

    heroku repo:reset
    
  4. Перейдіть до пульта Heroku так, як зазвичай; це перезавантажить все.


Для цього вам може знадобитися встановити інструменти репо Heroro. Зробітьheroku plugins:install https://github.com/heroku/heroku-repo.git
Ной

1

Скажімо, вам потрібно буде змінити конфігураційний файл на віддаленому сервері, як тільки ви створили порожнє (оголене) сховище, скажімо

root@development:/home/git/repository/my-project# cat config 

там ти побачиш

[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true

Ви зробите це неправдивим до істинного, і я видалив logallrefupdates = true (не впевнений у його використанні!)

до

[core]
repositoryformatversion = 0
filemode = true
bare = true

Ви можете перевірити наступне

$ git remote show origin
* remote origin
Fetch URL: my-portal@development:/home/XYZ/repository/XYZ
Push  URL: my-portal@development:/home/XYZ/repository/XYZ
HEAD branch: (unknown)

Ця гілка HEAD: (невідомо) буде показана, якщо ви не можете натиснути. Тож якщо гілка HEAD невідома, ви повинні змінити голою на справжню, і після успішного натискання ви можете використовувати її повторно

git remote show origin

і ти побачиш

 HEAD branch: master

0

Для мене робочим рішенням є:

НА ПОДАВАННЯ:

git checkout -b some_tmp_name

НА МІСЦЕ:

git push

НА ПОДАВАННЯ:

git checkout master
git branch -d some_tmp_name

Але це не справжнє рішення, це просто вирішення.


Це дійсне рішення, якщо у вас немає центрального сховища.
Рік

0

Про всяк випадок, якщо хтось вважає це корисним. Для мене це була проблема дозволів сервера git. Я перевірив проект із початкового і натисніть простий файл, і тоді я отримав "Відхилити Push: Push to origin / master було відхилено"


-1

За допомогою Git два звичайних (не голі) сховища не можуть натискати / перетягувати файли безпосередньо та назад. Має бути посереднє голе сховище. Мабуть, це схоже на подружню пару, яка має дитину, і пара розлучається. Батьки не розмовлятимуть між собою, але вони спілкуватимуться через дитину.

Отже, у вас є одне сховище, ви клонуєте це сховище до голого сховища, а потім клонуєте це до третього. Перший і третій можуть обмінюватися інформацією через другий сховище, оголене. Я думаю, це має сенс, оскільки ви не хочете, щоб хтось міг перевіряти речі у вашому сховищі без вашої згоди, оскільки це може спричинити конфлікти злиття тощо.

Отже, ось приклад:

На ПК у ~ / робочій області

git init
echo "line 1" > afile.txt
git add .
git commit -m ‘initial import’
git clone --bare . ../remote-repository.git
git remote add origin ../remote-repository.git
git push --set-upstream origin master

На ноутбуці, в ~ / робочому просторі (не робіть git init тощо)

git clone //LJZ-DELLPC/remote-repository.git/ .

// Потім зробіть різні коміти та натисніть на них:

echo "line 2" > afile.txt
git add afile.txt
git commit -m 'added line 2'
git push    

Потім поверніться на ПК, в ~ / робочу область

git pull

// Потім зробіть різні коміти та натисніть на них:

git push

На ноутбуці git pull

і так далі..

Ось абсолютний конкретний приклад - все на одній машині, скопійоване прямо з вікна команди, так що ми будемо знати, що жодних кроків не залишилось, що це дійсно спрацювало тощо:

lylez@LJZ-DELLPC ~
$ cd gitdir
/home/lylez/gitdir

lylez@LJZ-DELLPC ~/gitdir
$ ls

lylez@LJZ-DELLPC ~/gitdir
$ mkdir repo1

lylez@LJZ-DELLPC ~/gitdir
$ cd repo1
/home/lylez/gitdir/repo1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git init
Initialized empty Git repository in /home/lylez/gitdir/repo1/.git/

lylez@LJZ-DELLPC ~/gitdir/repo1
$ echo "line 1" > afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git commit -m 'initial import'
[master (root-commit) f407e12] initial import
 1 file changed, 1 insertion(+)
 create mode 100644 afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git clone --bar . ../repo1-bare-clone
Cloning into bare repository '../repo1-bare-clone'...
done.

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git remote add origin ../repo1-bare-clone

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git push --set-upstream origin master
Branch master set up to track remote branch master from origin.
Everything up-to-date

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cd ..

lylez@LJZ-DELLPC ~/gitdir
$ ls
repo1  repo1-bare-clone

lylez@LJZ-DELLPC ~/gitdir
$ mkdir repo1-remote

lylez@LJZ-DELLPC ~/gitdir
$ cd repo1-remote
/home/lylez/gitdir/repo1-remote

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git clone ../repo1-bare-clone .
Cloning into '.'...
done.

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ echo "line 2" >> afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git commit -m 'added line 2'
[master 5ad31e0] added line 2
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 260 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/lylez/gitdir/repo1-remote/../repo1-bare-clone
   f407e12..5ad31e0  master -> master

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cd ../repo1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cat afile.txt
line 1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ../repo1-bare-clone
   f407e12..5ad31e0  master     -> origin/master
Updating f407e12..5ad31e0
Fast-forward
 afile.txt | 1 +
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cat afile.txt
line 1
line 2

lylez@LJZ-DELLPC ~/gitdir/repo1
$ echo "line 3" >> afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git commit -m 'added line 3'
[master 3fa569e] added line 3
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 265 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ../repo1-bare-clone
   5ad31e0..3fa569e  master -> master

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cd ../repo1-remote/

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1
line 2

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/lylez/gitdir/repo1-remote/../repo1-bare-clone
   5ad31e0..3fa569e  master     -> origin/master
Updating 5ad31e0..3fa569e
Fast-forward
 afile.txt | 1 +
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1
line 2
line 3

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git --version
git version 2.1.1

lylez@LJZ-DELLPC ~/gitdir/repo1-remote

Це приклад того, що працює, і пояснення чому. Тут взагалі немає дезінформації, крім вашого коментаря.
Lyle Z

1
"За допомогою Git два звичайних (не голі) сховища не можуть натискати / перетягувати файли безпосередньо та назад безпосередньо" - За винятком того, що вони можуть.
Ендрю С

Чудово, розмістіть конкретний приклад замість нападу.
Lyle Z

Або ви могли це google? stackoverflow.com/questions/1764380/…
Ендрю С

Перша відповідь у потоці, на якому ви перебуваєте на сайті, починається з ", але згідно з git ready та офіційною вікі git, вам слід лише натиснути на оголене репо." Наступна відповідь зазначає: "Якщо ви хочете спробувати просто натиснути master -> master, тоді команда просто: git push origin", і це просто не працює, і на це впливає мільйон публікацій. Остання відповідь починається з "Я б запропонував на вашому сервері мати голий репозиторій та локальні робочі (не голі) репости.", Саме це я запропонував.
Lyle Z

-3

Моє рішення (використовується)

  1. Оформити замовлення "майстер" на віддаленому сервері
  2. Працюйте локально на гілці «dev»
  3. Натисніть зміни на віддалений розробник
  4. Об'єднайте розробник у головний на віддаленому

бінго

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.