git: надежно переключается на отдельную HEAD, а затем восстанавливает HEAD, все из скрипта - PullRequest
4 голосов
/ 12 августа 2010

Итак, вот сценарий.У меня есть скрипт, который запускает некоторые тесты.Мне нужно сделать другой скрипт, который принимает в качестве параметра имя коммита git, а затем выполняет следующее:

  1. Сохраняет текущее состояние фиксации - имя ветви или безымянный коммит.
  2. Переключение наотсоединенный HEAD с указанным коммитом
  3. Запускает тестовый сценарий для этого коммита
  4. Переключается обратно, чтобы HEAD был таким же, каким он был до этого дела

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

Я чувствую, что на этот вопрос должно быть легко ответить, так какзапуск тестового сценария для предыдущего коммита кажется очень распространенной задачей для автоматизации.Но я не могу найти какой-либо простой набор команд для этого.

(аналогично тому, что pushd / cd / popd делает для текущего рабочего каталога).

Ответы [ 2 ]

3 голосов
/ 12 августа 2010

Если это в сценарии, только для одного этого случая вам не нужно делать ничего сверхъестественного, просто сохраните, где HEAD была раньше, и проверьте это снова после:

# If HEAD is a sym-ref, the first assignment will work
# otherwise, it's detached, so get the SHA1 with rev-parse
if ! head=$(git symbolic-ref HEAD 2>&1); then
    head=$(git rev-parse HEAD)
fi
# trim a refs/heads/ prefix; no-op otherwise
head=${head#refs/heads/}


# now go on and do your stuff, test, whatever you like

# then return to where you were
# This will ERASE ANY LOCAL CHANGES.
git checkout -f $head

Это имеет преимущество в работе независимо от того, что вы делаете в середине - в частности, вы можете выполнять там много операций git - возможно, слияние тестов, или вишня - выбрать коммит для тестирования (возможно, тестирование этого коммита, возможно, оно содержитнекоторые настройки конфигурации сборки исключительно для тестирования).Так как эти операции создают коммиты, они приводят к сбою подхода HEAD@{1} (вместо этого вам нужно HEAD@{2}).Еще лучше, если ваше тестирование фактически включает создание временных ветвей , это все равно будет работать, в то время как подход @{-1} не сработает.

(Плюс, насколько я могу судить, HEAD@{1} всегда проверяет коммит , на который ссылается HEAD в этот момент, а не ветвь, которая затем указывала на этот коммит. Этот вид имеет смысл, поскольку ветвь могла измениться с тех пор.)

0 голосов
/ 12 августа 2010

попробуй (не проверял)

git checkout HEAD@{1}

на "переключается обратно на HEAD", как это было до вашего checkout xxx.

См. Также "HEAD и ORIG_HEAD в Git "


Все остальные спецификации ревизии находятся здесь: rev_parse, раздел «УКАЗАНИЯ ПЕРЕСМОТРОВ» .
Например, чтобы вернуться к предыдущей ветке , вы можете попробовать @{-1}.

Только что протестировал (опция «предыдущий HEAD»):

Простое git-репо с 3 файлами, добавленными в три коммита (a, затем b, затем c):

C:\git\tests\p3>git log --oneline
6e5b961 c
66c68e3 b
77e9a40 a

Я оформляю первый коммит (DETACHED HEAD)

C:\git\tests\p3>git checkout 77e9a40
Note: moving to '77e9a40' which isn't a local branch
If you want to create a new branch from this checkout, you may do so
(now or later) by using -b with the checkout command again. Example:
  git checkout -b <new_branch_name>
HEAD is now at 77e9a40... a

C:git\tests\p3>dir
08/12/2010  12:27 PM                 4 a.txt

Я пытаюсь вернуться к предыдущему HEAD, прежде чем сделать DETACHED HEAD:

C:\git\tests\p3>git checkout HEAD@{1}
Previous HEAD position was 77e9a40... a
HEAD is now at 6e5b961... c

Работает!

Вы получаете верный коммит, но не правильную ветвь (т. Е. Вы все еще находитесь в отдельном режиме)

C:\git\tests\p3>git branch
* (no branch)
  master

В этой конфигурации попытка вернуться в предыдущую ветку не будет работать

C:\git\tests\p3>git checkout HEAD@{-1}
error: pathspec 'HEAD@{-1}' did not match any file(s) known to git.

Таким образом, единственное реальное решение вернуться к HEAD (не к фиксации в отдельном режиме) - это сначала запомнить его

git symbolic-ref HEA

См. Ответ Джефроми .

...