我想使用这个工作流程:
- 阶段性的一些变化。
- 将未暂存的更改保存到存储中。
- 对阶段中的事物做一些事情(构建、测试等)。
- 犯罪。
- 恢复未暂存的更改。
有没有办法做第2步?
例子:
git init
echo one >file
git add file
git commit
echo two >>file
git add file
echo three >>file
git stash push
test
git commit
git stash pop
git stash push
有一个选项--keep-index
可以完全满足您的需要。
所以,运行git stash push --keep-index
。
这可以通过 3 个步骤完成:保存分阶段更改、存储其他所有内容、使用分阶段更改恢复索引。基本上是:
git commit -m 'Save index'
git stash push -u -m 'Unstaged changes and untracked files'
git reset --soft HEAD^
这将完全符合您的要求。
git stash save --keep-index
另外,回复:
为什么不在暂存后提交您的更改?– 申
答:因为您应该始终检查已测试的代码 :) 这意味着,您只需要使用即将提交的更改来运行测试
所有这一切,当然,作为一个有经验的程序员,你天生就有测试和审查这些变化的冲动——只是部分开玩笑
--keep-index
/的问题-k
在 Git 中仅存储工作树(未暂存的更改)比应有的困难。接受的答案,以及相当多的其他答案,隐藏了未暂存的更改,并按照要求通过--keep-index
.
然而,不明显的是,它--keep-index
也隐藏了分阶段的变化。分阶段的更改最终会出现在阶段和存储中。这很少是人们想要的,因为对存储的任何临时更改都可能在以后弹出存储时导致冲突。
这个别名非常适合仅暂存工作副本更改:
stash-working = "!f() { \
git commit --quiet --no-verify -m \"temp for stash-working\" && \
git stash push \"$@\" && \
git reset --quiet --soft HEAD~1; }; f"
它临时提交分阶段的更改,从剩余的更改中创建一个存储(并允许其他参数,例如--include-untracked
和--message
作为别名参数传递),然后重置临时提交以取回分阶段的更改。
它类似于@Simon Knapp 的答案,但有一些细微的差别——它用于--quiet
临时操作,并且它接受任意数量的 stash 参数push
,而不是硬编码-m
,它确实添加--soft
到 final重置,以便索引保持启动状态。它还用于--no-verify
提交以避免从预提交挂钩(HT:@Granfalloner)更改工作副本。
对于仅存储分阶段更改(别名stash-index
)的相反问题,请参见此答案。
你git version 2.7.4
可以这样做:
git stash save --patch
将git
要求您将更改添加或不添加到存储中。
然后你只需回答y
或n
您可以像往常一样恢复工作目录:
git stash pop
或者,如果您想将保存的更改保存在存储中:
git stash apply
要将未标记(未添加到提交)的文件添加到存储,请运行以下命令:
git stash -k
如果您想将新添加的文件(未暂存 - 不是绿色)也包含到存储中,请执行以下操作:
git stash -k -u
然后您可以提交暂存文件。之后,您可以使用以下命令取回最后隐藏的文件:
git stash pop
Git 没有仅存储未暂存更改的命令。
但是,Git 确实允许您指定要存储的文件。
git stash push --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb
如果您只想在这些文件中存储特定更改,请添加该--patch
选项。
git stash push --patch --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb
该--include-untracked
选项允许您存储未跟踪的文件。
git stash push --include-untracked --message 'Untracked files' -- app/controllers/widgets_controller.rb test/controllers/widgets_controller_test.rb
运行git help stash
(或man git-stash
)以获取更多信息。
注意:如果您的未分级更改相当混乱,@alesguzik 的答案可能更容易。
扩展以前的答案,我有时会进行一组复杂的更改,但希望先提交单独的更改。例如,我可能已经发现了一个错误或其他不正确的代码,我想在分阶段更改之前修复它们。一种可能的方法是:
首先存储所有内容,但保留分阶段的更改
$ git stash save --keep-index [--include-untracked]
现在也单独存储分阶段的更改
$ git stash 保存
进行更改以进行修复;和测试;提交他们:
$ git add [--interactive] [--patch]
$ git commit -m"修复..."
现在恢复先前阶段的更改:
$ git stash pop
解决任何冲突,并注意如果存在冲突,git 将应用但不会删除该顶级存储条目。
(...然后提交分阶段的更改,并恢复所有其他更改的存储,然后继续...)
与问题相关的另一个提示:
当您使用
$ git stash save --keep-index
您可能希望给 stash 一条消息,这样当您执行 a 时,git stash list
您之前存储的内容会更加明显,特别是如果您通过进一步保存来遵循该 stash 操作。例如
$ git stash save --keep-index "更改尚未上演"
(尽管实际上它确实包含其他答案中提到的所有更改)。
例如,上面可能紧跟着:
$ git stash save “功能 X 的阶段性更改”
但请注意,您不能使用
$ git stash apply "stash@{1}" ### ✘ 并不完全符合您的要求
只恢复未暂存的更改。
I use an an alias, which accepts a string to use as a message to the stash entry.
mystash = "!f() { git commit -m hold && git stash push -m \"$1\" && git reset HEAD^; }; f"
Which:
-u
or -a
),--soft
to keep it in the index).这是(在我看来)最好的解决方案,它完全符合 OP 的要求。它只存储未暂存的、跟踪的文件——没有不必要的提交或存储所有更改的文件--keep-index
它列出了所有未暂存的、跟踪的更改 ( git diff --name-only
) 将换行符转换为空格 ( | tr '\n' ' '
) 并使用以下命令存储所有这些文件git stash push
:
git stash push $(git diff --name-only | tr '\n' ' ')
从 Git 2.35+(2022 年第一季度)开始,您现在可以使用--staged
标志 ( man )来仅暂存index 中git stash push
的更改。
由于您的问题完全相反,我们有两个选择:
git stash push --staged # Stash staged changes
git stash # Stash everything else
git stash pop stash@{1} # Restore staged changes stash
git stash push --staged
我从另一个 S/O 帖子的这个答案中获得了这些信息。
2022:我在“ Stash only staged changes in git - is it possible? ”中提到,Git 2.35(2022 年第一季度)带有“ git stash push --staged
” (man):
此选项仅对推送和保存命令有效。
仅存储当前暂存的更改。
这类似于基本git commit
的,除了状态被提交到存储而不是当前分支。
2019:该命令的现代形式是git stash push [--] [<pathspec>...]
,因为 Git 2.16+(git stash save
已弃用)
您可以将其与通配符形式结合使用,例如:
git stash push --all --keep-index ':(glob)**/*.testextension'
但这不适用于 Windows 的 Git,直到 Git 2.22(2019 年第二季度),请参阅issue 2037,考虑到git stash
已在 C 中重新实现(而不是 shell 脚本)
请参阅Thomas Gummerer ( ) 的提交 7db9302(2019 年 3 月 11 日)。
请参阅Johannes Schindelin ( ) 的commit 1366c78和commit 7b556aa(2019 年 3 月 7 日)。(由Junio C Hamano 合并 -- --在0ba1ba4 提交中,2019 年 4 月 22 日)tgummerer
dscho
gitster
内置:再次
stash
处理路径规范:(glob)
在将路径规范列表传递给 时
git add
,我们需要小心使用原始形式,而不是路径规范的解析形式。这会有所不同,例如在调用时
git stash -- ':(glob)**/*.txt'
其中原始形式包含
:(glob)
前缀,而解析后的形式不包含。但是,在内置的 中
git stash
,我们传递了已解析(即不正确)的表单,并且git add
会失败并显示错误消息:fatal: pathspec '**/*.txt' did not match any files
在从工作树中
git stash
删除更改的阶段,即使refs/stash
实际上已成功更新。
据我所知,目前不可能使用仅保存工作树中未暂存的更改git stash push
,即保存索引状态的更改。此命令保存工作树中的所有更改(分阶段和非分阶段更改),即从 HEAD 状态更改,即使使用也--keep-index
将工作树状态设置为索引状态而不是 HEAD 状态的选项(从而在恢复用 ) 从 HEAD 状态更改。如果有一个只保存未暂存更改的选项(对我来说这个选项有缺陷),那将非常方便,因为它已经有一个只保存暂存更改的选项。git stash pop
git stash push
-U|--unstaged
--keep-index
-S|--staged
所以暂时你必须效仿
git stash push --unstaged
git stash pop
有一个临时文件:
git diff >unstaged
git restore .
git apply unstaged
rm unstaged
您的用例是在提交部分更改之前进行测试,它已经在参考文档中,但有缺陷的选项--keep-index
会产生冲突。这是带有模拟选项的版本-U|--unstaged
:
git init
echo one >file
git add file
git commit
echo two >>file
git add file
echo three >>file
git diff >unstaged
git restore .
test
git commit
git apply unstaged
rm unstaged
为了更好地理解存储,我认为在每个步骤中查看工作树、索引和 HEAD 的状态很重要。让我们来看看你的用例。
git init
在职的 | 指数 | 头 |
---|
echo one >file
在职的 | 指数 | 头 |
---|---|---|
一 |
git add file
在职的 | 指数 | 头 |
---|---|---|
一 | 一 |
git commit
在职的 | 指数 | 头 |
---|---|---|
一 | 一 | 一 |
echo two >>file
在职的 | 指数 | 头 |
---|---|---|
一 | 一 | 一 |
二 |
git add file
在职的 | 指数 | 头 |
---|---|---|
一 | 一 | 一 |
二 | 二 |
echo three >>file
在职的 | 指数 | 头 |
---|---|---|
一 | 一 | 一 |
二 | 二 | |
三 |
git diff >unstaged
git restore .
在职的 | 指数 | 头 |
---|---|---|
一 | 一 | 一 |
二 | 二 |
test
git commit
在职的 | 指数 | 头 |
---|---|---|
一 | 一 | 一 |
二 | 二 | 二 |
git apply unstaged
rm unstaged
在职的 | 指数 | 头 |
---|---|---|
一 | 一 | 一 |
二 | 二 | 二 |
三 |