как сбросить рабочее дерево git на обновленный коммит - PullRequest
2 голосов
/ 07 марта 2019

Мне нужно расширить данный инструмент скриптом Bash, который должен работать с Linux и MacOS. Скрипт получает 2 параметра:

  1. Местоположение хранилища (файловая система, ssh, http (s), ...)
  2. A коммит , например ветвь, тэг, коммит хеш

Я не могу влиять на параметры

Результат выполнения скрипта должен быть таким:

  • хранилище клонируется в фиксированный пункт назначения (всегда одинаково для одного хранилища)
  • рабочее дерево репозитория должно соответствовать последнему состоянию кометы (например, если это была ветвь, вершина этой ветви)

Если хранилище (пока) не существует локально, процедура так же проста, как

git clone $REPO_SOURCE $REPO_DIR
cd $REPO_DIR
git checkout $REPO_REF

Мой вопрос: рассмотрим, что хранилище уже клонировано в /repos/foo. После обновления git fetch, как мне обновить этот репозиторий до $REPO_REF?

  • Если $REPO_REF была ветвью, git checkout $REPO_REF && git pull должно работать
  • Если это был хеш коммита, обновление не требовалось (просто git checkout $REPO_REF?)
  • Если это был тег, то тег мог быть перемещен в начало координат, как с этим справиться?
  • Как обращаться с другими крайними случаями?

Существует ли простой способ reset-repository-to-this-commitsh, поэтому хранилище ведет себя так же, как если бы оно было недавно клонировано?

Боковые узлы:

  • Один и тот же репозиторий может использоваться с разными commitish , но только последовательно: гарантируется, что скрипт не вызывается более одного раза одновременно
  • Все внешние изменения в хранилище всегда могут быть отменены без уведомления
  • Хотя удаление и клонирование хранилища будет работать, оно нецелесообразно из-за их размеров и является некрасивым решением
  • Нет (git) изменений не требуется, так что проверить отсоединенную головку можно.

Ответы [ 2 ]

2 голосов
/ 07 марта 2019

Единственный полностью надежный, но удобный способ - использовать другой Git (тот, который вы клонируете, но не можете), чтобы разрешить имя для вас. Тогда у вас есть хеш-идентификатор, и хеш-идентификатор универсален.

Если имя является именем ветви или тега, вы можете использовать git ls-remote для выполнения этого шага. Если это может быть какая-то другая формулировка (например, master~13), вам здесь не повезло. Итак, если вам нужно разрешить имя локально:

  • Если соблюдать дисциплину тега, тег никогда не будет перемещаться. Это означает, что если у вас есть существующий клон с тегом, у него есть правильный тег, и у вас все в порядке, а если у вас есть существующий клон, у которого нет тега, вы можете добавить тег и разрешить его. .

  • Если дисциплина тегов не соблюдается, вам придется удалить и заново создать теги (фу), или же заново изобрести удаленные теги: скопировать их refs/tags/* имена в ваше refs/rtags/<remote>/* пространство имен. См. Git - извлечение удаленного тега, когда два пульта имеют одинаковое имя тега .

  • Если у вас есть имя ветви или что-то, связанное с именем ветви, включите имя ветви в собственное имя удаленного отслеживания (например, замените master~13 на refs/remotes/origin/master~13) и разрешите его.

В любом случае, теперь у вас есть хэш-идентификатор и вы можете использовать режим отсоединенного HEAD.

1 голос
/ 09 марта 2019

Используя «стандартный» git-клон, вы можете сделать следующее:

# cleanup old cruft
git reset --hard HEAD
git clean -fdx

# detach from current branch (if on any)
git checkout --detach
# delete all local branches
git for-each-ref --format="%(refname:strip=2)" refs/heads |xargs -r git branch -D
# fetch and update all remote refs and tags
git fetch --force --all --tags --prune --prune-tags
# checkout
git checkout "$COMMITISH"

Таким образом, вы можете положиться на git checkout, чтобы выполнять свою работу как обычно, и вам не нужно копировать какие-либо эвристики, ярлыки и т. Д.

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