仅对分阶段文件运行测试:`git stash -k -u`和`git stash pop`将引发部分分段文件的冲突

李岡諭*_*李岡諭 5 git git-stash

TL;博士

我想在提交之前仅使用暂存文件运行测试:

  1. git stash save -k -u 在测试之前存储未分级/未跟踪的文件/更改
  2. 使用分阶段文件运行测试
  3. git stash pop 在步骤1恢复更改/文件.

问题是使用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)
Run Code Online (Sandbox Code Playgroud)

现在使用git stash -k -u然后git stash pop会引发冲突.

证明这个问题

,Git提供了三个阶段更改之前提交:staged,unstageduntracked.

任何更改都将添加到unstaged.之前提交,你可以挑选一些线条或文件,并将它们添加到staged通过git add.

现在,在添加了一些代码后staged,我想运行只有分段文件的测试,以确保它们适合提交,所以我需要隐藏unstageduntracked更改(新文件)git stash -k -u并保持staged更改.

比方说,我有3个文件更改:文件A完全暂存,文件B部分暂存(部分代码),文件C是未跟踪的新文件.

[staged]
  file A
  file B (only stage some of code)
[unstaged]
  file B
[untracked]
  file C (new file)
Run Code Online (Sandbox Code Playgroud)

运行后git stash -k -u,所有未暂存/未跟踪的更改都将被隐藏.

[staged]
  file A
  file B (only stage some of code)
[unstaged/untracked]
  <none, clean>
Run Code Online (Sandbox Code Playgroud)

这就是问题所在.运行测试后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
Run Code Online (Sandbox Code Playgroud)

我需要一种方法,stash pop不会丢失所有更改的暂存/未暂停状态.通过添加其他更改来保持暂存文件对于提交或完成测试非常重要.

使用解决方案更新:运行该过程的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
# http://stackoverflow.com/questions/41304610/
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')
Run Code Online (Sandbox Code Playgroud)

tor*_*rek 2

这不是完整的答案\xe2\x80\x94see如何从“git stash save --all”恢复?更多\xe2\x80\x94,但是虽然这是一个有吸引力的过程,并且一旦错误出现,它将起作用git stash得到修复它就会起作用,但今天有点危险。

\n\n

如果您已经修复了错误,或者不介意稍微危险地生活,:-) 您可以使用此过程:

\n\n
    \n
  1. 运行git stash save -k -u 并确保它保存了一些东西(例如,比较来自git rev-parse refs/stash)。
  2. \n
  3. 运行您的测试。
  4. \n
  5. git reset --hard && git clean -df(可选,包括-q两者)。git reset --hard仅当测试修改提交的文件时才需要,并且git clean当测试创建未跟踪的文件时才需要 。
  6. \n
  7. 跑步git stash pop --index。请注意,--index这里的 很关键。您可能希望使用-q您可能也
  8. \n
\n\n

您可能希望使用save和,而不是使用和,并将您的储物袋存储在不同的引用下(您可以在完成后以任何您喜欢的方式操作和/或删除)。当然,如果您要走这么远,您可能想编写自己的修改版pop --indexcreateapply --indexgit stash脚本,以首先避免当前的错误。

\n\n
\n\n

有一种完全不同的、在我看来更简单的运行测试的方法:

\n\n
    \n
  1. 创建一个空的临时目录。
  2. \n
  3. 将当前索引转换为树,然后将该树读入临时目录。(或者使用git checkout-index将索引提取到临时目录中。无论哪种情况,请记下环境变量GIT_WORK_TREEGIT_DIR,或前端的--git-dir和参数--work-treegit参数。)
  4. \n
  5. 在临时目录中运行测试。
  6. \n
  7. 放弃临时目录。
  8. \n
\n\n

这避免了git stash save错误,并且只需对步骤 2 稍加修改,即可让您测试任何修订版。有两个明显的缺点:您需要一个地方来存储临时树,并且临时树不在工作树所在的位置。这些问题的严重程度取决于您的存储库和测试。

\n