Как я могу sh изменить чей-то репозиторий (я являюсь соавтором) из подмодуля моего собственного репозитория? - PullRequest
0 голосов
/ 25 февраля 2020

Итак, у меня есть свой собственный репозиторий, давайте назовем его «мой», который содержит подмодульный репозиторий «их». У меня есть доступ к их удаленному хранилищу, так что я могу напрямую вносить изменения в него.

Я пытаюсь вернуть sh изменения, которые я внес в "их", в их удаленный репозиторий GitHub, но я не могу заставить его работать. Я могу сделать sh изменения в моем удаленном репозитории «мой» на GitHub, и там видны новые коммиты на «их». Но когда я посещаю их GitHub, он не добавляет последние коммиты.

Разве подмодули не должны быть обычными репозиториями, внутри другого с некоторыми дополнительными метаданными? Если да, то почему "git pu sh" из каталога "их" не работает? Я попытался зафиксировать и нажать из «их», а затем «cd ..» и зафиксировать / pu sh из «моего», но это тоже не сработало.

Я попробовал шаги перечисленные здесь: Git подмодуль pu sh безрезультатно. Я могу только предположить, что, поскольку я пытаюсь отправить sh в хранилище, которое мне не принадлежит, нужно что-то еще сделать?

~/Mine$ git remote -v                                                                                                                                                                                                        
origin  https://github.com/myUser/Mine.git (fetch)                                                                                                                                                                                
origin  https://github.com/myUser/Mine.git (push) 

~/Mine/Their$ git remote -v                                                                                                                                                                                                    
origin  https://github.com/theirUser/Theirs.git (fetch)                                                                                                                                                                                        
origin  https://github.com/theirUser/Theirs.git (push) 

Ответы [ 2 ]

0 голосов
/ 25 февраля 2020

Вы правы: подмодуль является хранилищем само по себе. Это означает, что вы можете cd или chdir войти в подмодуль и начать использовать его так же, как и любой другой репозиторий Git, включая запуск git fetch, git checkout, git commit и т. Д.

Что делает подмодуль подмодулем, так это тот факт, что какой-то другой Git, расположенный где-то над подмодулем, управляет подмодулем, обычно выполняя в нем git checkout <em>hash-id</em>. Это переводит подмодуль в режим, который Git называет detached HEAD . (Управляющий Git - это суперпроект .)

Этот режим "отсоединенного HEAD" немного сложен. Вы можете делать новые коммиты в этом режиме, но когда вы это делаете, они не находят большинством обычных средств. Их легко найти на данный момент по специальному имени HEAD, но это специальное имя HEAD будет принудительно настроено суперпроектом, который chdir войдет в подмодуль и запустит git checkout <em>hash-id</em> опять же, теряя 1 совершенных вами коммитов.

Чтобы отправить в какой-либо другой репозиторий Git сделанные вами коммиты в вашем подмодуле Git, вы должен дать этим коммитам имя в другом Git хранилище. Обычно это означает, что им нужно дать название филиала. Нет жесткого требования использовать имя ветки в вашем хранилище, так как вы можете выполнить:

git push <remote-or-URL> HEAD:<name>

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

Как правило, это означает, что для работы в репозитории Git, который действует как субмодуль для некоторого суперпроекта, вы должны использовать следующую последовательность: 2

  1. Введите подмодуль. Начиная с шага 3, вы будете работать с ним как с обычным Git хранилищем.

  2. Выйдите из режима отключенного HEAD , выбрав ветку имя от до git checkout или путем создания имени ветви, указывающего на текущий коммит. Обратите внимание, что если вы выберете какое-нибудь существующее имя ветки, это может быть другой коммит от current commit. Или это может быть такой же коммит, что и текущий коммит.

    Помните, что хранилище суперпроектов ранее сообщало Git: использовать этот необработанный коммит, его ха sh Идентификатор , чтобы войти в режим отключенного HEAD Теперь мы получаем из отдельного режима HEAD, который требует выбора или создания имени ветви. Если вы выберете какое-нибудь существующее имя ветви, вы застрянете с любым коммитом, который выберет это имя ветви. Но если вы разрабатываете новые коммиты в хранилище подмодулей, вы, вероятно, захотите, чтобы имя ветки запомнило их.

  3. Теперь создайте новый коммит (ы) обычным способом. Используйте git push обычным способом. Коммиты будут или не будут go в получающем репозитории обычным способом, который коммиты делают или не делают. Если они попадут в принимающее хранилище, то имя филиала этого хранилища будет создано или обновлено обычным способом.

  4. Как только все будет сделано, выйдите из подмодуля. репозиторий, возвращающийся в репозиторий суперпроекта. Настало время сделать новый коммит в суперпроекте .

Я уже несколько раз упоминал, что суперпроект Git продолжает контролировать подмодуль Git , Он делает chdir в подмодуле Git и запускает git checkout <em>hash-id</em>. Ключ здесь состоит из двух частей:

  • Когда суперпроект Git делает это с подмодулем?
  • Где делает суперпроект Git получить необработанный га sh ID?

Ответ на первый вопрос сложен: git submodule update делает это, но не всегда; 3 git checkout --recursive делает это (всегда); различные другие операции могут иногда делать это, в зависимости от параметров и настроек. То есть, это не произойдет до тех пор, пока вы не попросите об этом, но не всегда очевидно, что вы просите, чтобы это произошло. Что мы собираемся сделать, это убедиться, что мы обращаемся к второй точке, прежде чем это произойдет снова.

Ответ на второй вопрос - где суперпроект Git получает необработанный га sh ID - то, что он получает его от , фиксирует в суперпроекте . Но вы сделали новый коммит в подмодуле и доставили его вверх по потоку в какой-нибудь другой Git репозиторий, так что теперь пришло время сделать новый коммит в суперпроекте , чтобы запишите right ha sh ID, то есть ha sh ID нового коммита, который вы сделали в подмодуле.

Как всегда, ни один коммит не может быть изменен; и, как всегда, Git делает новым коммитом из того, что находится в index (он же область подготовки ). Когда вы извлекаете какой-либо существующий коммит, Git считывает файлы из этого коммита в область index / staging. Если хранилище выступает в качестве суперпроекта для некоторого подмодуля, этот шаг также считывает желаемый га sh ID (в этом подмодуле) из коммита в индекс. Поскольку это уже не нужный идентификатор ha sh, теперь ваша задача - поместить новый ha sh ID в индекс.

Команда, которая делает это в суперпроекте git add. Как всегда, git add записывает данные в индекс. Для обычного файла он записывает в индекс копию этого файла. 4 Однако для подмодуля он:

  • входит в подмодуль на мгновение;
  • спрашивает , что Git: каков необработанный идентификатор ha sh для коммита, идентифицируемого вашим HEAD? (git rev-parse HEAD);
  • вставляет полученный идентификатор ha sh, какой бы он ни был, в индекс суперпроекта Git, в слот для этого подмодуля.

Это работает, если подмодуль находится в отсоединенном HEAD состояние или нет, потому что git rev-parse HEAD всегда возвращает необработанный идентификатор ha sh текущего коммита.

Итак, после git add path/to/submodule идентификатор ha sh идентификатора коммита, который выбранный вами (и фактически сделанный и выдвинутый) теперь записывается в index в суперпроекте. Ваш следующий коммит будет записывать , что raw ha sh ID.

Предполагая, что все остальное также готово, теперь вы можете запустить git commit, чтобы сделать новый коммит в суперпроекте (который, по-видимому, находится и был все время в состоянии прикрепленного-HEAD, на каком-то имени ветви). Как только вы сделаете этот новый коммит суперпроекта, вы будете готовы git push сделать его как обычно.

Обратите внимание на тщательный порядок шагов здесь:

  1. Введите подмодуль.
  2. Сделайте коммит (ы) в подмодуле, для простоты в ветвях, но как бы вы их ни делали, все в порядке.
  3. Отправьте эти коммиты туда, где люди клонируют субмодуль от, так что , что Git имеет их. Этот шаг требует установки имени ветви или тега в этом другом Git.
  4. Теперь, когда другие люди могут получить доступ к этой фиксации в репозитории origin субмодуля , make и pu sh коммит в суперпроекте, который ссылается на необработанный идентификатор коммита подмодуля sh ID.

Возможно - из-за распределенной природы Git - сделать совершить коммит в вашем подмодуле, но не pu sh где угодно, затем сделать коммит в вашем суперпроекте и pu sh it. Любой, кто получает этот новый коммит, получает коммит, который по необработанному номеру ha sh ID ссылается на коммит, который он не только не имеет, но даже не может получить . Поэтому шаг 3 («сделать коммит доступным для всех») должен произойти до push на шаге 4. («Make commit» на шаге 4 может произойти раньше - просто будьте осторожны, чтобы не извлечь его sh и повторить его с любым обновленным коммитом ha sh, если фиксация подмодуля должна быть переделано по любой причине.)


1 Терять здесь означает «трудно найти». Сами коммиты сразу не исчезнут sh: у них тот же льготный период, что и у других потерянных коммитов, и вы можете использовать подмодуль Git HEAD reflog, чтобы найти их, так же, как вы нашли потерянный фиксирует в любом репозитории, потому что подмодуль является , в конце концов, просто еще одним репозиторием.

2 Поскольку Git - это набор инструментов, а не предварительно упакованный Решение, есть много других способов достижения вашей цели. Это просто один очень гибкий способ.

3 В частности, git submodule update имеет много обновлений режимов . С некоторыми аргументами вы можете указать git submodule update проверить имя в подмодуле, что приведет к присоединению HEAD (а не отдельного) в первую очередь! Это часть того, на что ссылается сноска 2. Подробная работа git submodule update довольно сложна, поэтому я стараюсь избегать этих вариантов в этом ответе.

4 Технически, он записывает объект blob с правильным содержимым файла - или повторно использует существующий объект BLOB-объекта без изменений, если это возможно, - а затем записывает идентификатор индекса * ha sh объекта индекса в индекс, а не фактическое содержимое файла. Но эффект такой, как если бы Git скопировал файл в индекс, если вы не опуститесь до уровня git ls-files --stage и git update-index.

0 голосов
/ 25 февраля 2020

Как только коммиты будут выполнены, pu sh разветвит репо (ie "мой"). С вашей вилки откройте запрос на извлечение в правильной ветке. Как только запрос на получение одобрен и объединен, вы можете вытащить изменения из апстрима в локальное хранилище.

Затем изменения будут добавлены в «их» репозиторий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...