Как мне извлечь один файл (или изменения в файл) из git stash?

Я создал класс treeview с флажками, наследующими ttk.Treeview, но флажки не являются ttk.Checkbutton, но изображения отмеченных, непроверенных и тристатных флажков.

import tkinter as tk
import tkinter.ttk as ttk

class CheckboxTreeview(ttk.Treeview):
    """
        Treeview widget with checkboxes left of each item.
        The checkboxes are done via the image attribute of the item, so to keep
        the checkbox, you cannot add an image to the item.
    """

    def __init__(self, master=None, **kw):
        ttk.Treeview.__init__(self, master, **kw)
        # checkboxes are implemented with pictures
        self.im_checked = tk.PhotoImage(file='checked.png')
        self.im_unchecked = tk.PhotoImage(file='unchecked.png')
        self.im_tristate = tk.PhotoImage(file='tristate.png')
        self.tag_configure("unchecked", image=self.im_unchecked)
        self.tag_configure("tristate", image=self.im_tristate)
        self.tag_configure("checked", image=self.im_checked)
        # check / uncheck boxes on click
        self.bind("", self.box_click, True)

    def insert(self, parent, index, iid=None, **kw):
        """ same method as for standard treeview but add the tag 'unchecked'
            automatically if no tag among ('checked', 'unchecked', 'tristate')
            is given """
        if not "tags" in kw:
            kw["tags"] = ("unchecked",)
        elif not ("unchecked" in kw["tags"] or "checked" in kw["tags"]
                  or "tristate" in kw["tags"]):
            kw["tags"] = ("unchecked",)
        ttk.Treeview.insert(self, parent, index, iid, **kw)

    def check_descendant(self, item):
        """ check the boxes of item's descendants """
        children = self.get_children(item)
        for iid in children:
            self.item(iid, tags=("checked",))
            self.check_descendant(iid)

    def check_ancestor(self, item):
        """ check the box of item and change the state of the boxes of item's
            ancestors accordingly """
        self.item(item, tags=("checked",))
        parent = self.parent(item)
        if parent:
            children = self.get_children(parent)
            b = ["checked" in self.item(c, "tags") for c in children]
            if False in b:
                # at least one box is not checked and item's box is checked
                self.tristate_parent(parent)
            else:
                # all boxes of the children are checked
                self.check_ancestor(parent)

    def tristate_parent(self, item):
        """ put the box of item in tristate and change the state of the boxes of
            item's ancestors accordingly """
        self.item(item, tags=("tristate",))
        parent = self.parent(item)
        if parent:
            self.tristate_parent(parent)

    def uncheck_descendant(self, item):
        """ uncheck the boxes of item's descendant """
        children = self.get_children(item)
        for iid in children:
            self.item(iid, tags=("unchecked",))
            self.uncheck_descendant(iid)

    def uncheck_ancestor(self, item):
        """ uncheck the box of item and change the state of the boxes of item's
            ancestors accordingly """
        self.item(item, tags=("unchecked",))
        parent = self.parent(item)
        if parent:
            children = self.get_children(parent)
            b = ["unchecked" in self.item(c, "tags") for c in children]
            if False in b:
                # at least one box is checked and item's box is unchecked
                self.tristate_parent(parent)
            else:
                # no box is checked
                self.uncheck_ancestor(parent)

    def box_click(self, event):
        """ check or uncheck box when clicked """
        x, y, widget = event.x, event.y, event.widget
        elem = widget.identify("element", x, y)
        if "image" in elem:
            # a box was clicked
            item = self.identify_row(y)
            tags = self.item(item, "tags")
            if ("unchecked" in tags) or ("tristate" in tags):
                self.check_ancestor(item)
                self.check_descendant(item)
            else:
                self.uncheck_descendant(item)
                self.uncheck_ancestor(item)



if __name__ == '__main__':
    root = tk.Tk()
    t = CheckboxTreeview(root, show="tree")
    t.pack()
    t.insert("", 0, "1", text="1")
    t.insert("1", "end", "11", text="1")
    t.insert("1", "end", "12", text="2")
    t.insert("12", "end", "121", text="1")
    t.insert("12", "end", "122", text="2")
    t.insert("122", "end", "1221", text="1")
    t.insert("1", "end", "13", text="3")
    t.insert("13", "end", "131", text="1")
    root.mainloop()

Улучшенная версия CheckboxTreeview доступен в модуле ttkwidgets .

666
задан PlagueHammer 9 July 2009 в 23:08
поделиться

4 ответа

В man-странице git stash вы можете прочитать это (в разделе «Обсуждение» сразу после описания «Опции»):

Шкатулка представлена ​​в виде коммита, дерево которого записывает состояние рабочего каталога, и его первым родителем является коммит в HEAD при создании тайника.

Таким образом, вы можете рассматривать stash (например, stash@{0} является первым / верхним тайном) как коммит слияния и использовать:

$ git diff stash@{0}^1 stash@{0} -- <filename>

Объяснение: stash@{0}^1 ярлык означает первого родителя данного тайник, который, как указано в объяснении выше, является коммитом, при котором изменения были спрятаны Мы используем эту форму "git diff" (с двумя коммитами), потому что stash@{0} / refs/stash является коммитом слияния, и мы должны указать git, против какого родителя мы хотим использовать diff. Более загадочно:

$ git diff stash@{0}^! -- <filename>

также должны работать (см. Справочную страницу git rev-parse для объяснения синтаксиса rev^! в разделе «Задание диапазонов»).

Аналогично, вы можете использовать git checkout , чтобы извлечь один файл из тайника:

$ git checkout stash@{0} -- <filename>

или сохранить его под другим именем:

$ git show stash@{0}:<full filename>  >  <newfile>

или

$ git show stash@{0}:./<relative filename> > <newfile>

( обратите внимание , что здесь < полное имя файла > является полным путем к файлу относительно верхнего каталога проекта (думаю: относительно stash@{0})) .


Возможно, вам потребуется защитить stash@{0} от расширения оболочки, т. е. использовать "stash@{0}" или 'stash@{0}'.

983
ответ дан Jakub Narębski 9 July 2009 в 23:08
поделиться

Самая простая концепция для понимания, хотя, возможно, и не самая лучшая, это то, что вы изменили три файла и хотите сохранить один файл.

Если вы сделаете git stash, чтобы спрятать их все, git stash apply, чтобы вернуть их снова, а затем git checkout f.c в рассматриваемом файле, чтобы эффективно сбросить его.

Если вы хотите распаковать этот файл, запустите git reset --hard, а затем снова запустите git stash apply, воспользовавшись тем, что git stash apply не очищает diff из стека.

5
ответ дан Philluminati 9 July 2009 в 23:08
поделиться

Если вы используете git stash apply , а не git stash pop , он применит тайник к вашему рабочему дереву, но при этом сохранит тайник.

После этого вы можете добавить / зафиксировать файл, который вам нужен, а затем сбросить оставшиеся изменения.

41
ответ дан 22 November 2019 в 21:35
поделиться

Вы можете получить разницу для тайника с помощью " git show stash @ {0} " (или любого другого номера тайника; см. "Git stash list"). Раздел diff для одного файла легко извлечь.

10
ответ дан 22 November 2019 в 21:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: