tl;dr
在提交之前,我想仅使用暂存的文件运行测试:
git stash save -k -u
用于在测试之前存储未暂存/未跟踪的文件/更改- 使用暂存的文件运行测试
git stash pop
以还原第一步中的更改/文件。
问题在于使用 git stash pop
将导致部分暂存的文件出现冲突。解决冲突将导致丢失部分暂存/未暂存的更改(您需要重新选择部分行以再次进行暂存)。
更新:如果您想了解运行此过程的shell脚本,请跳转到最后一节获取更多信息。
注意:仅对部分暂存的相邻行(或足够接近的行)会导致此问题。 例如,如果您在某个文件中有6个新行更改:
1 +| a (add to staged)
2 +| b (add to staged)
3 +| c (add to staged)
4 | d (keep unstaged)
5 | e (keep unstaged)
6 | f (keep unstaged)
现在使用
git stash -k -u
,然后git stash pop
将引发冲突。
演示问题
Git在提交之前提供了三个更改阶段:staged
、unstaged
和untracked
。
任何更改都将添加到unstaged
。在提交之前,您可以选择一些行或文件,并通过git add
将它们添加到staged
中。
现在,在将一些代码添加到staged
之后,我想只使用暂存的文件运行测试,以确保它们适合提交,因此我需要通过git stash -k -u
隐藏unstaged
和untracked
更改(新文件),并保留staged
更改。
例如,假设我有3个文件更改:文件A完全暂存,文件B是部分暂存(一些代码),文件C是一个新文件,未被跟踪。
[staged]
file A
file B (only stage some of code)
[unstaged]
file B
[untracked]
file C (new file)
运行
git stash -k -u
命令后,所有未提交/未跟踪的更改都会被隐藏。[staged]
file A
file B (only stage some of code)
[unstaged/untracked]
<none, clean>
问题来了。在运行测试后,再运行 git stash pop
时,因为文件 B 是部分暂存的,它会引发冲突。我确定在暂存和测试时没有更改文件 B。
我想知道如何像之前暂存时那样,在运行 git stash pop
时自动合并而不产生冲突。
我的工作流程
我认为这是一个非常普通的工作流程。
development start
|
[make changes (unstaged)]
|
(pick changes to staged for commit by `git add`)<---|
| |
V (pick other changes to fulfill tests)
[partial staged/unstaged] |
| |
(stash unstaged changes by `git stash -k -u`) |
| |
(run tests only with staged files for commit) |
| |
(restore stashed files by `git stash pop`) |
| |
|------------<if test failed>-------------|
|
<if test success>
|
[commit staged files by `git commit`]
|
V
keep development or next commit
我需要一种方法来进行
stash pop
,同时不丢失所有更改的staged/unstaged状态。保留staged文件对于提交或通过添加其他更改来完成测试非常重要。
解决方案更新:运行该程序的shell脚本
根据@torek的回答,我编写了一个shell脚本来仅使用staged文件运行测试:#!/bin/sh -e
# stash all unstaged changes
# (-k: unstaged files; -u: new added files; -q: quite)
echo '--------------------------------------------------------------'
echo '---- Stash all unstaged/untracked files (git stash -k -u) ----'
echo '--------------------------------------------------------------'
BEFORE_STASH_HASH=$(git rev-parse refs/stash)
git stash -k -u -q
AFTER_STASH_HASH=$(git rev-parse refs/stash)
if [ "$BEFORE_STASH_HASH" == "$AFTER_STASH_HASH" ]; then
echo '\n\n---- Stash failed! Please check and retry. ----\n\n';
exit 1;
fi;
# run test only with staged files
echo '-------------------'
echo '---- Run tests ----'
echo '-------------------'
<run your tests here> || #### <=== replace your test command here
(echo '\n\n---- Tests failed! Please fix it before commit. ----\n\n')
# restore all stashed changes
# https://dev59.com/a53ha4cB1Zd3GeqPXJ6F
echo '-----------------------------------------------------------'
echo '---- Restore all stashed files (git stash pop --index) ----'
echo '-----------------------------------------------------------'
git reset --hard -q &&
git clean -df -q &&
git stash pop --index -q ||
(echo '\n\n---- Restore failed! Please check and fix it. ----\n\n')
git stash pop
无论如何都会触发自动合并,但是你不能传递合并标志,例如-s theirs
,这将解决此问题。我想指出的是,如果同一文件中的暂存和未暂存更改不足以引起冲突,自动合并将正常解决 - 我认为这个问题的术语“部分暂存”并不清楚,并且我认为在早期的 git 版本中也存在此问题。 - André Sassi--keep-index
和--include-untracked
有关。请注意,使用git stash
在此情况下会产生 三个 提交:一个用于索引状态,一个用于工作树状态,另一个用于保存未跟踪的文件。恢复存储状态需要重新设置并清理。详情请参见 https://dev59.com/VWIj5IYBdhLWcg3wIx_W。 - torek