Как реплицировать git-checkout, используя только команды сантехники?

Я хотел бы избежать вызова фарфоровых команд из своих сценариев, но есть ли способ получить поведение git checkout <commit>, используя только команды сантехники, такие как checkout-index? Меня особенно интересует влияние на рабочую копию: при условии, что все чисто, checkout удаляет файлы, которые отслеживались в старой HEAD и отсутствовали в новой. checkout-index, похоже, не имеет представления об удалении файлов. Самое близкое, что я могу придумать, это позвонить

git diff-tree -p <old> <new> | git apply

но вычисление всего diff кажется излишне дорогим. Есть ли способ лучше?


person Jack O'Connor    schedule 23.07.2014    source источник
comment
Любая причина, по которой вы просто не позвоните git checkout ...?   -  person Oliver Charlesworth    schedule 24.07.2014
comment
Да, не усложняй себе жизнь без нужды.   -  person ThiefMaster    schedule 24.07.2014
comment
В конечном счете, я хочу иметь больше контроля над тем, как происходит оформление заказа. Например, checkout может удалять игнорируемые файлы, а я хочу этого избежать (повышение безопасности). Но я хочу проложить удаленные файлы (снижение безопасности), не используя --force для прокладки всего. Это часть скрипта, который использует git под прикрытием для хранения деревьев файлов, и checkout очень близко к тому, как я хочу, чтобы мой скрипт вел себя, но не совсем. Я подумал, что если бы я мог получить checkout с помощью сантехнических команд, я мог бы настроить его оттуда, хотя, пожалуйста, дайте мне знать, есть ли другой способ получить этот элемент управления.   -  person Jack O'Connor    schedule 24.07.2014
comment
Вы действительно проверяли, что diff-tree работает медленно? checkout в основном различает все, чтобы понять, что делать в первую очередь. (Конечно, checkout не создает патчи, а затем не применяет их, и, вероятно, вам не следует этого делать.)   -  person Edward Thomson    schedule 24.07.2014
comment
@EdwardThomson diff-tree, вероятно, то, что я хочу, но я не уверен, во что передать его вывод. Есть ли способ применить этот diff к рабочей копии, кроме хака git apply выше? Было бы достаточно просто написать скрипт на Python, который брал бы список удалений и фактически выполнял их, но я боюсь, что это будет медленно.   -  person Jack O'Connor    schedule 24.07.2014


Ответы (1)


Вы ищете два дерева git read-tree -um. Он использует базовое дерево (обычно вы загружаете его HEAD), целевое дерево и (неявно) индекс и рабочее дерево. Мне было трудно понять таблицу, описывающую его поведение, поэтому у меня есть собственная шпаргалка, переформатированная, которая, во всяком случае, имеет для меня больше смысла. Во всяком случае, он реализует git checkout.

git read-tree -um H M  # `I` is the (implicit) index, GIT_INDEX_FILE

                    Legend

        H       Original tree (usually HEAD:)
        I       Indexed tree
        M       Merge target tree

        H->I     \
        H->M      } status in second relative to first
        I->M     /

        "-"     file exists in neither
       new      exists only in second
       deleted  exists only in first
       same     exists in both, unchanged
       changed  exists in both, different
      (blank)   irrelevant or all cases not otherwise given

        keep    keep current version
        fail    whole command fails, no changes
       delete   delete worktree file


      H->I      H->M      I->M

                          same     keep

     deleted   changed             fail
     deleted   deleted             delete
     deleted    same               delete unless Index empty, else use M
                same               keep

      same     changed             worktree clean: use M; dirty: fail
      same     deleted             worktree clean: deleted; dirty: fail

      new        -                 keep
      new       new      changed   fail
     changed   changed   changed   fail
     changed   deleted             fail


note: "index empty" identifies an initial checkout, where HEAD has been
set but never loaded.  git can't currently distinguish between a
delete-everything index and an initial-checkout index.
person jthill    schedule 28.07.2014
comment
+1. Шпаргалка мне нравится. Я завершил свой ответ примером, используя git read-tree -um. - person VonC; 28.07.2014
comment
Спасибо! Я никогда бы не догадался. - person Jack O'Connor; 29.07.2014
comment
Пожалуйста. Я бы тоже не догадался, не всегда легко увидеть, что вы можете заставить git делать. Я знаю, что на самом деле не получил эту команду, пока не разозлился на таблицу в документе и не потратил время на то, чтобы сделать свою собственную. - person jthill; 29.07.2014