Репликация «git checkout ‹commit› с PyGit2

Я пытаюсь воспроизвести поведение команды «git checkout (commit)», где (commit) — это ссылка на конкретную фиксацию, а не имя ветки.

При использовании этой команды «ГОЛОВА» репозитория указывает на фиксацию (отделенная головка), а рабочий каталог находится в том же состоянии, что и в этой фиксации.

На данный момент мне удалось сделать так, чтобы HEAD репозитория указывал на фиксацию с помощью PyGit2:

def go(self, repo_name, version):
    repo = pygit2.Repository(bdd[repo_name])
    #commit = repo.revparse_single(version)
    #repo.reset(version, pygit2.GIT_RESET_HARD)
    repo.set_head(pygit2.Oid(hex=version))
    print repo.head_is_detached

Моя проблема в том, что я не могу найти, как откатить рабочий каталог, как это делает Git CLI. Я пытался использовать:

  • repo.checkout_head() : ничего не делает в рабочем каталоге.
  • repo.checkout() : Сбой с GitError: X conflicts prevent checkout

Есть ли способ воспроизвести это поведение без использования Repository.reset(ref, pygit2.GIT_RESET_HARD)?


person Maeln    schedule 10.05.2017    source источник
comment
Чист ли ваш рабочий каталог перед попыткой запустить repo.checkout()?   -  person Nils Werner    schedule 10.05.2017
comment
@NilsWerner Я пытаюсь сделать repo.checkout() после того, как изменил HEAD, чтобы он указывал на фиксацию. На данный момент рабочий каталог содержит все, что было в последней сделанной фиксации, поэтому рабочий каталог не является чистым с точки зрения HEAD, я думаю.   -  person Maeln    schedule 10.05.2017
comment
Так что просто не комбинируйте set_head() (это делает рабочее пространство грязным) и checkout() (ожидается, что рабочее пространство будет чистым). Просто используйте checkout().   -  person Nils Werner    schedule 10.05.2017
comment
@NilsWerner Моя проблема в этом случае заключается в том, что Repository.checkout(ref) берет ссылку и не принимает объект Commit, ни его шестнадцатеричное представление, ни Oid. Поэтому я не могу найти, как checkout() выполнить конкретную фиксацию в pygit2.   -  person Maeln    schedule 10.05.2017
comment
repo.checkout(version) где version строка sha1 не работает?   -  person Nils Werner    schedule 10.05.2017
comment
@NilsWerner Это не так. Repository.checkout(ref) вызовет lookup_reference(refname), если переданный вами объект не является ни Reference, ни 'HEAD'. Если вы дадите ему Commit или коммит Oid, он вернет ошибку типа (lookup_reference принимает только строку), а если вы дадите строку SHA1 коммита, он вернет ValueError: (commit string): The given reference name (commit string) is not valid.   -  person Maeln    schedule 10.05.2017
comment
И как вам удалось заставить checkout() показывать ошибку GitError: X conflicts prevent checkout?   -  person Nils Werner    schedule 10.05.2017
comment
Вы можете использовать checkout() без каких-либо аргументов. Если вы это сделаете, он сделает checkout_index(). Это checkout_index(), которые действительно возвращают GitError: X conflicts ....   -  person Maeln    schedule 10.05.2017
comment
Низкоуровневая проверка — git read-tree -um HEAD $target && git update-ref HEAD $target; pygit2, по-видимому, понимает только чтение одного дерева и ни один из вариантов этого, поэтому, несмотря на то, что он выполняет проверку и слияние, а также любое количество других операций, он не предлагает ничего, кроме грубого макета фактического git. Похоже, вы могли бы добавить ссылку на свой коммит, проверить это, затем сбросить HEAD и удалить ссылку.   -  person jthill    schedule 12.05.2017
comment
@jthill Я попробовал это (создайте ссылку с целевой фиксацией, затем проверьте эту ссылку и проверьте «refs/heads/master», чтобы вернуться), и это отлично работает для моего варианта использования. Можете ли вы поместить это как ответ, чтобы я мог подтвердить это?   -  person Maeln    schedule 15.05.2017
comment
Насколько я понимаю pygit2, это почти невозможно, так почему бы просто не запустить исходную команду git напрямую, вместо того, чтобы тратить энергию на ее моделирование через pygit2?   -  person Done Data Solutions    schedule 15.05.2017
comment
@rrschmidt Я не могу использовать команду git из-за ограничений в моем проекте. Я вынужден использовать libgit2/pygit2.   -  person Maeln    schedule 15.05.2017


Ответы (2)


Низкоуровневая проверка - это git read-tree -um HEAD $target && git update-ref HEAD $target; pygit2, по-видимому, понимает только чтение одного дерева и ни один из вариантов этого, поэтому, однако, он выполняет проверку и слияние и любое количество других операций, он не предлагает больше, чем грубый макет фактического мерзавец Похоже, вы могли бы запутаться, добавив ссылку в свой коммит, проверить это, затем сбросить HEAD и удалить ссылку.

person jthill    schedule 15.05.2017

repo.checkout_tree может напрямую использовать коммит. После того, как это будет сделано, вам все еще понадобится файл set_head. Кроме того, передайте следующую стратегию в checkout_tree, если вы хотите эквивалент «git reset»: pygit2.GIT_CHECKOUT_FORCE | pygit2.GIT_CHECKOUT_RECREATE_MISSING

person Grant Husbands    schedule 08.11.2018