仅在特定分支上删除Git stashes

时间:2014-09-29 09:16:16

标签: git github branch git-stash

git stash drop [<stash>]似乎没有分支选项。

来源:http://git-scm.com/docs/git-stash

我想这是一个非常明显的要求,删除在特定分支上完成的所有stashes,一旦该分支已合并为master并且不再需要。有办法吗?我有大约40-50个被删除的藏匿处。

1 个答案:

答案 0 :(得分:1)

Stashes并非真正&#34;在分支机构上,他们会参与特定的提交(请参阅this answer一个不同的问题,以获得我的图表意思)。也就是说,任何具体的提交都可以说是&#34; on&#34;零个或多个分支,因此给定分支名称,您可以找到并测试每个存储:

let to_drop = empty_set()
for (s in all_stashes):
    let c = commit_of(s)
    if is_on_branch(c, branch):
        add_to_set(s, to_drop)
for s in reverse(to_drop):
    execute("git stash drop " + s)

或多或少(这是伪Python,我发现伪代码比伪shell更像)。这定义了一个存储在一个分支上的概念&#34;&#34;这是我在这个答案的其余部分中使用的。

(倒退的原因是&#34;所有的藏匿处&#34;很可能会发现&#34;藏匿@ {0},藏匿@ {1},藏匿@ {2},... ,藏匿@ { n }&#34;当我们放下一些藏匿处时,所有编号较高的藏匿处都会重新编号,因此如果我们向后工作,我们可以避免重新编号剩余的藏匿处。)

要将上述内容转换为工作的shell脚本代码,我们只需要进行明显的翻译。这里有一堆碎片(很大程度上未经测试,有些碎片经过隔离测试):

# Produce a list of all refs/stash@{n} and sha-1.
# Might be nice if we could use --reverse here, but
# we can't.
all_stashes() {
    git log -g --pretty=format:"%gd %H" refs/stash
}

(上面只是git stash list被黑了一点来打印藏匿名和完整哈希值。)

# Determine whether the given commit ($2) is on the given branch ($1).
# If the commit is on multiple branches, we say "yes" if ANY of those
# match $1 (but the match must be exact).  Note that the while loop
# runs in a subshell so we use an eval trick here.  (Probably would
# be better to just write this in awk.)
#
# Note that "git branch --contains" prints "  A -> B" for indirect
# branches; we ignore these.  It prefixes the current branch with "* "
# and others with "  ", and we discard these prefixes.  You may want
# to fiddle with the first decision.
is_on() {
    local branch
    eval $(git branch --contains $2 | sed -e '/ -> /d' -e 's/^..//' |
        while read branch; do
            [ "$branch" = "$1" ] && echo return 0
        done)
    return 1
}

# Given branch name ($1), find all stashes whose parent commit
# is on that branch.
stashes_on_branch() {
    local refname hash

    all_stashes | while read refname hash; do
        is_on "$1" ${hash}^ && echo "$refname"
    done
}

(顺便说一下,sh似乎允许return 0 1 2 3但bash抱怨,所以上面的内容可能需要在某些系统上回显return 0之后实际上突破循环。)

用于反转行列表,&#34; tac&#34;将是理想的,但大多数系统没有它。我们可以使用bash数组等,但这样做要简单得多,虽然效率很低,但如果分支名为-e,则会遇到问题:

# Reverse a list of lines
reverse() {
    local line text nl=$'\n'
    while read line; do
        text="$line$nl$text"
    done
    echo -n "$text"
}

通过所有这些作品,现在可以轻而易举地放弃&#34;&#34;&#34;给定的分支:

for stash in $(stashes_on_branch foobranch); do git stash drop $stash; done

所有这一切,只是因为分支合并并不一定意味着所有的东西都是&#34; on&#34;应删除 分支。如果这是您的特定工作流程,那很好;但这很不寻常,因为存储脚本应该有这个内置的特殊原因。