Полный сброс git-репо обратно в состояние клона? - PullRequest
0 голосов
/ 29 марта 2019

У меня есть ящик с репо, мы назовем его апстрим.У меня есть еще один ящик, который клонировал его давным-давно, мы назовем его локальным.

Многое могло случиться с локальным, у него могли быть ветви, теги и т. Д. Я хочу сбросить локальный набыть в том же состоянии, как если бы это был современный git clone.Я не хочу просто потерять изменения в рабочем каталоге, я бы хотел, чтобы все состояния были одинаковыми.

Есть другие решения дляэта проблема (обычно при использовании клонирования в temp, нюкинга .git и перемещения по нему), но мне интересно, есть ли другой способ сделать это с помощью просто git.Я бы предпочел не загружать заново то, что мне не нужно.

Ответы [ 2 ]

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

Во-первых, отмените любую одиночную ветвь или поверхностность, если только новый клон не был бы одиночной и / или мелкой (в этом случае do любая одиночная ветвь или мелкость, но обмеление в конце процесса). Удалите все другие нестандартные настройки, которые накапливались в .git/config, кроме тех, которые были бы установлены вручную в вашей операции git clone.

Затем, при необходимости, переименуйте один удаленный входящий / исходный пульт, удалив все остальные. Предположим, например, что вы намеревались использовать удаленное имя git clone по умолчанию origin, но в существующем хранилище для этого используется upstream1 и имеется второй удаленный upstream2. Удалите upstream2git remote remove) и переименуйте upstream1 в origingit remote rename).

Затем запустите git fetch на удаленном имени, которое у вас есть, что бы это ни было, с опциями --prune и --prune-tags. По умолчанию origin, поэтому, если вы сохраняете значение по умолчанию, вы можете просто git fetch -p, поскольку это будет означать git fetch =p origin. (Я не уверен на 100%, что происходит с настройкой восходящего потока ветки current , какой бы она ни была, если бы это был какой-то другой пульт, так что вы можете просто запустить git fetch -p origin, чтобы быть в безопасности в все дела.)

Этот следующий шаг предполагает не одну ветвь. Я не уверен, что означает origin/HEAD, когда вы используете клон с одной ветвью, скажем, ветви X, в то время как HEAD источника имеет значение master. Если вас не беспокоит единственная ветвь (или вы никогда не используете origin/HEAD), то все равно это не имеет значения, но я пытаюсь завершить здесь.

Теперь запустите git remote set-head --auto на оставшемся пульте, например, git remote --set-head origin --auto. Есть небольшая гонка между предыдущим шагом и этим. Если вышестоящий Git, который у вас будет git clone d, постоянно перемещает свою HEAD из ветви в ветку, это как бы неизбежно: то, какое HEAD вы получите от них, будет зависеть от , когда вы сделали ваш git clone. Однако это покажет разницу между выполнением git clone и выполнением этой последовательности команд. Если вышестоящий Git не перемещает свою ГОЛОВУ, здесь нет расы: их HEAD стабильно между git fetch и git remote set-head.

Теперь выберите название локального филиала, которое вы хотите иметь. Как правило, в свежем git clone со всеми значениями по умолчанию, одна локальная ветвь, которую вы бы выбрали, это та, которую они рекомендуют с их HEAD, которая теперь копируется в ваш origin/HEAD из-за git remote set-head. Так что прочитайте это (например, git branch -r origin или git symbolic-ref refs/remotes/origin/HEAD), чтобы увидеть, что это за ветка. (Вероятно, это master.) Проверьте , что имя ветви - это должно произойти, даже если ваш Git должен создать его - и убедиться, что его восходящий поток установлен на соответствующий удаленный имя отслеживания (например, origin/master), при необходимости изменив его. Используйте git reset --hard @{upstream} для:

  • переместите его, если git checkout не создал его;
  • сбросить ваш индекс и рабочее дерево

, а затем удалите остальные и используйте git clean -dfx, чтобы удалить все каталоги и файлы, которые не были бы извлечены из начального git checkout, который git clone выполнял бы как последний шаг.

Теперь все готово, если только вы не хотели мелкого клона, и в этом случае вам, возможно, теперь понадобится увеличить размер текущего хранилища. При желании вы можете запустить git gc --prune=all для очистки файлов пакета.

Резюме, за вычетом всех возни с одноотраслевым и мелким и тому подобное

Если мы сможем сделать несколько разумных предположений, процессы станут намного проще. Допущения:

  • без единой ветки, без поверхностности, и только один пульт origin, который уже настроен правильно;
  • нет местный филиалы с именем origin/*, чтобы поднять вас ниже;
  • нет других локальных настроек для очистки (например, вы не git config user.name в этом хранилище); и
  • нет желания суетиться с git remote set-head (вы можете сделать это в любое время, хотя).

В этом случае процесс такой, который в значительной степени можно вырезать и вставить, просто измените master на любую ветку, которую вы хотите сохранить:

git fetch -p --prune-tags
git checkout master             # or whatever branch you intended to keep
git branch --set-upstream-to=origin/master  # use correct origin/ name here
git reset --hard origin/master  # update work-tree
git clean -dfx                  # remove non-committed stuff from work-tree
git for-each-ref --format='%(refname:short)' refs/heads |
    while read name; do
        [ "$name" == "master" ] && continue   # skip the one to keep
        git branch -D "$name"                 # delete the others
    done

(вышеизложенное не проверено, поэтому будьте осторожны!). Шаг --set-upstream-to, как правило, не нужен (он будет неактивным), но я включил его для полноты.

Обратите внимание, что шаг git clean -dfx потенциально удаляет много потенциально полезных файлов. Вы сказали, что хотели бы получить состояние, которое у вас было бы, если бы вы запускали git clone, и ни один из них потенциально полезные файлы будут скопированы на git clone. Поскольку вы, вероятно, делаете это для избегания данного git clean данного типа эффекта , вы, вероятно, захотите пропустить или, по крайней мере, изменить много, шаг git clean.

0 голосов
/ 29 марта 2019

Вы можете использовать эту команду, чтобы увидеть ваш самый первый коммит и его хеш:

git log --pretty=oneline | tail -1

Затем выполните эту команду, чтобы сбросить этот хеш:

git reset --hard [commit hash]
...