Git隐藏未缓存:如何把所有未分期的变化?

假设在git控制的项目中做了两组更改。一组是上演的,另一组不是。

我想通过在此状态(提交之前)运行我的项目来重新检查阶段性更改。有什么简单的方法可以把所有非阶段性的变化都收起来,只留下阶段性的变化?所以我需要从我的项目中消失的非阶段性变化,但要存储在某个地方以供进一步工作。

这听起来很像git stash命令。但是git stash将把非阶段性和阶段性的变化远离我的项目。我找不到类似git stash uncached的东西。

61890 次浏览
< p > 更新2: < br > 我不知道为什么人们抱怨这个答案,它似乎与我完美地工作,对于未提取的文件,你可以添加-u标志

完整的命令变成git stash --keep-index -u

下面是来自git-stash帮助的一个片段

如果使用了——keep-index选项,则所有更改都已添加到

.

.

如果使用了——include-untracked选项,则所有未跟踪的文件都将被删除 还藏好了,然后用git清理干净,留下工作 目录处于非常干净的状态。如果使用——all选项 然后将被忽略的文件存储和清理 无路径的文件。< / p >

这是它的动图:

enter image description here

更新:

虽然这是选定的答案,但很多人指出[下面的答案](https://stackoverflow.com/a/34681302/292408)是正确的,我建议大家去看看 我今天(31/1/2020)对git版本2.24.0再次测试了我的答案,我仍然相信它是正确的,我在上面添加了一个关于未跟踪文件的小注释。 如果你认为它不能工作,请同时提到你的git版本 < p > 旧的答案: < br > 如果使用--keep-index选项,则所有已添加到索引中的更改都保持不变:

git stash --keep-index

git-stash的文档:

测试部分提交

你可以使用git stash save --keep-index当你想要创建两个或 在工作树中的更改中有更多的提交,并且您希望进行测试 提交前的每个更改:

# ... hack hack hack ...
$ git add --patch foo            # add just first part to the index
$ git stash save --keep-index    # save all other changes to the stash
$ edit/build/test first part
$ git commit -m 'First part'     # commit fully tested change
$ git stash pop                  # prepare to work on all other changes
# ... repeat above five steps until one commit remains ...
$ edit/build/test remaining parts
$ git commit foo -m 'Remaining parts'

但是,如果你只想直观地检查阶段性的变化,你可以尝试difftool:

git difftool --cached

我发现标记的答案对我不起作用,因为我需要一个真正只隐藏我的非阶段性变化的东西。标记的答案git stash --keep-index同时存储阶段性和非阶段性的更改。--keep-index部分也只是在工作副本上保持索引完整。这对OP有用,但只是因为他问了一个与他真正想要的答案略有不同的问题。

我发现的唯一隐藏非阶段性变化的方法是根本不使用隐藏:

git diff >unstaged.diff
git apply -R unstaged.diff

你也可以使用git restore .git checkout -- .来代替git apply -R unstaged.diff

工作,工作,工作……

git apply unstaged.diff
rm unstaged.diff

Git:隐藏未分阶段的更改

这将隐藏所有你没有git添加的修改:

git stash -k

注意,新创建的(和未添加的)文件将保留在你的工作目录中,除非你也使用-u开关。

git stash -k -u

此外,你的工作目录必须是干净的(即所有的变化需要添加),当你git stash pop以后。

http://makandracards.com/makandra/853-git-stash-unstaged-changes

正如一些人指出的那样,公认的答案也隐藏着阶段性的变化。这里有一种方法可以做到这一点,而不用在隐藏的地方进行阶段性的更改。

这个想法是做一个临时提交你的阶段性变化,然后保存非阶段性的变化,然后取消临时提交:

# temp commit of your staged changes:
$ git commit --message "WIP"


# -u option so you also stash untracked files
$ git stash -u


# now un-commit your WIP commit:
$ git reset --soft HEAD^

在这一点上,您将有一个非阶段性更改的隐藏,并且只会在工作副本中显示阶段性更改。

由于到目前为止,这里的各种答案似乎都有它们自己的复杂性/局限性,所以我想提供更多的替代方案,以涵盖我个人需要的所有特定边缘情况。

博士tl;

列出暂存(未删除)文件:

git diff --staged --diff-filter=d --name-only

列出未暂存(未删除)的文件:

git diff --diff-filter=d --name-only

列出非暂存/未跟踪文件:

git ls-files --modified --others --exclude-standard

只存储阶段性文件(最初来自这个StackOverflow的答案,但略有调整):

git stash push --include-untracked -- $(git diff --staged --diff-filter=d --name-only)

只存储非暂存(非未跟踪)文件:

git stash push --keep-index -- $(git diff --diff-filter=d --name-only)

存储未暂存和未跟踪的文件:

git stash push --keep-index --include-untracked -- $(git ls-files --modified --others --exclude-standard)

存储阶段性/非阶段性文件,同时也将阶段性文件保存在索引中:

git stash push --keep-index

存储阶段性/非阶段性/不跟踪文件,同时也将阶段性文件保存在你的索引中:

git stash push --include-untracked --keep-index

完整的解释

git stash push允许我们提供一个<pathspec>,并且只保存与它匹配的文件:

git stash push -- <pathspec>

push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--pathspec-from-file=<file> [--pathspec-file-nul]] [--] [<pathspec>…​]

将您的本地修改保存到一个新的存储条目中,并将它们回滚到HEAD(在工作树和索引中)。该部分是可选的,提供了描述和存储状态。

<pathspec>…​

此选项仅对push命令有效。

新的隐藏条目仅为匹配路径规范的文件记录修改后的状态。然后,索引条目和工作树文件也只针对这些文件回滚到HEAD中的状态,而不匹配路径规范的文件则保持不变。

-u--include-untracked--no-include-untracked

当与pushsave命令一起使用时,所有未跟踪的文件也会被存储起来,然后用git clean清理。


git diff允许我们用--name-only列出当前未暂存的文件:

git diff --name-only

git diff [<options>] [--] [<path>…​]

此表单用于查看您相对于索引(下一次提交的暂存区域)所做的更改。

--name-only

只显示已更改文件的名称。

--diff-filter=\[(A|C|D|M|R|T|U|X|B)…​\[*\]\]

只选择被添加(A),复制(C), 删除(D),修改(M),重命名(R),其类型(即常规文件,符号链接,子模块,…)改变(T),未合并(U),未知(X),或配对已被破坏(B)的文件。可以使用过滤器字符的任何组合(包括none)。

同时,这些大写字母可以用小写字母来排除。例如,--diff-filter=ad排除添加和删除的路径。


git ls-files允许我们列出--modified文件和未跟踪(--others)文件:

git ls-files --modified --others --exclude-standard

git-ls-files -显示索引和工作树中的文件信息

-m--modified

在输出中显示修改后的文件

-o--others

在输出中显示其他(即未跟踪的)文件

--exclude-standard

在每个目录中添加标准的Git排除:. Git /info/exclude, .gitignore,以及用户的全局排除文件。

这里有一个简单的方法:

  1. 将下面的别名定义添加到您的.zshrc.bashrc.bash_profile
  2. 现在,任何时候你在这种情况下,只要输入gss,你就会有两个存储-一个包含所有的更改,另一个只包含阶段性的更改

你现在可以应用阶段性的变化,看看它们是否有效,如果你想提交它们。然后,稍后您还可以通过应用“all WIP”存储来引入未分阶段的更改并尝试这些更改。

alias gsts='git stash save'
alias gsv="git stash save --keep-index"


# How to Git Stash preserving staged/unstaged situation.
# 1. gsv will stash all and reset (remove) the unstaged, leaving only staged in staged state.
# 2. gsts will make a stash with your "good" (staged) files
alias gss='gsv all WIP && gsts staged WIP'

Git 2.35 (Q1 2022)开始,您现在可以通过git stash --staged保存阶段性更改。

因此,为了隐藏unstaged (无足迹的)更改:

git stash --staged          # stashes staged, leaving unstaged
git stash -u                # stashes unstaged & untracked
git stash pop "stash@{1}"   # pops staged back (but they're now unstaged)
git add -A                  # restages the previously staged changes

< >强然而< / >强,如果分级&未分阶段的变化影响相同的行,如git stash --staged将“部分”;在这种情况下,通过存储阶段性的更改失败,但留下两个阶段性的&unstaged。
在这种情况下,下面的方法(使用git commit)可能更好。


如果你想为它添加一个git 别名,将这个添加到你的.gitconfig:

[alias]
stash-unstaged = "!cd "${GIT_PREFIX:-.}"; f() { \
git stash --quiet --staged;                 \
git stash -u \"$@\";                        \
git stash pop --quiet \"stash@{1}\";        \
git add -A;                                 \
}; f"

用法:

git stash-unstaged -m "Stash Message"
<人力资源> <人力资源>

Git 2.35版本,

你可以通过利用git commit来分离阶段性和非阶段性的变化来隐藏unstaged (无足迹的):

git commit -m "TEMP"        # commits staged, leaving unstaged
git stash -u                # stashes unstaged & untracked
git reset --soft HEAD^      # undo commit, bringing staged back
与之前的方法(使用git stash --staged)不同,即使在分段&非分段更改影响相同的行。
但是,你可能需要解决合并冲突,当你弹出隐藏。


供你参考,要保存上演了的变化,只需先保存非暂存:

# Stash unstaged as shown previously
git commit -m "TEMP"
git stash -u
git reset --soft HEAD^


git stash -u                # stashes remaining staged
git stash pop "stash@{1}"   # pops unstaged back

这两个的别名:

[alias]
stash-unstaged = "!cd "${GIT_PREFIX:-.}"; f() { \
git commit --quiet -m \"TEMP\";             \
git stash -u \"$@\";                        \
git reset --quiet --soft HEAD^              \
}; f"
    

stash-staged = "!cd "${GIT_PREFIX:-.}"; f() {   \
git stash-unstaged --quiet;                 \
git stash -u \"$@\";                        \
git stash pop --quiet \"stash@{1}\";        \
}; f"