show用法 - git添加文件




只存储使用Git更改过的多个文件中的一个文件? (18)

快速回答

要在git中还原特定的已更改文件,您可以执行以下操作:

git checkout <branch-name> -- <file-path>

这是一个实际的例子:

git checkout master -- battery_monitoring/msg_passing.py

如何在我的分支上只隐藏多个已更改文件中的一个?


地方变化:

  • file_A(已修改)未上演
  • file_B(已修改)未上演
  • file_C(已修改)未上演

要仅使用file_C上的更改创建存储“my_stash”:

1. git add file_C
2. git stash save --keep-index temp_stash
3. git stash save my_stash
4. git stash pop [email protected]#{1}

完成。

说明

  1. file_C添加到暂存区域
  2. 创建一个名为“temp_stash”的临时存储,并将更改保存在file_C上
  3. 仅使用file_C上的更改创建想要的存储(“my_stash”)
  4. 将“temp_stash”(file_A和file_B)中的更改应用于本地代码并删除存储

您可以在步骤之间使用git status来查看正在进行的操作。


警告

正如评论中所指出的,这会将所有内容都放入存储中,无论是分阶段还是非分阶段。 -step-index只在保存完成后单独留下索引。 以后弹出存储时,这可能会导致合并冲突。

这将隐藏您之前未添加的所有内容。 只需git add你想要保留的东西,然后运行它。

git stash --keep-index

例如,如果要将旧提交拆分为多个变更集,则可以使用此过程:

  1. git rebase -i <last good commit>
  2. 将某些更改标记为edit
  3. git reset HEAD^
  4. git add <files you want to keep in this change>
  5. git stash --keep-index
  6. 根据需要修复问题。 不要忘记git add任何更改。
  7. git commit
  8. git stash pop
  9. 必要时,从#5开始重复。
  10. git rebase --continue

一个复杂的方法是首先提交一切:

git add -u
git commit // creates commit with sha-1 A

重置回原始提交,但从新提交中检出the_one_file:

git reset --hard HEAD^
git checkout A path/to/the_one_file

现在你可以存储the_one_file:

git stash

通过在重置回原始提交时将已提交内容保存在文件系统中进行清理:

git reset --hard A
git reset --soft HEAD^

是的,有点尴尬......


你也可以使用git stash save -p "my commit message" 。 通过这种方式,您可以选择将哪些帅哥添加到藏匿处,也可以选择整个文件。

每个块都会提示您一些操作:

   y - stash this hunk
   n - do not stash this hunk
   q - quit; do not stash this hunk or any of the remaining ones
   a - stash this hunk and all later hunks in the file
   d - do not stash this hunk or any of the later hunks in the file
   g - select a hunk to go to
   / - search for a hunk matching the given regex
   j - leave this hunk undecided, see next undecided hunk
   J - leave this hunk undecided, see next hunk
   k - leave this hunk undecided, see previous undecided hunk
   K - leave this hunk undecided, see previous hunk
   s - split the current hunk into smaller hunks
   e - manually edit the current hunk
   ? - print help

使用git stash push ,如下所示:

git stash push [--] [<pathspec>...]

例如:

git stash push -- my/file.sh

这是自2017年春季发布的Git 2.13开始提供的。


假设你有3个文件

a.rb
b.rb
c.rb

并且你想只存储b.rb和c.rb而不是a.rb

你可以做这样的事情

# commit the files temporarily you don't want to stash
git add a.rb
git commit -m "temp" 

# then stash the other files
git stash save "stash message"

# then undo the previous temp commit
git reset --soft HEAD^
git reset

你完成了! HTH。


另一种方法:

# Save everything
git stash 

# Re-apply everything, but keep the stash
git stash apply

git checkout <"files you don't want in your stash">

# Save only the things you wanted saved
git stash

# Re-apply the original state and drop it from your stash
git stash apply [email protected]{1}
git stash drop [email protected]{1}

git checkout <"files you put in your stash">

在我(再一次)来到这个页面之后我想出了这个并且不喜欢前两个答案(第一个答案就是没有回答这个问题而且我不喜欢使用-p交互模式) 。

这个想法与@VonC建议使用存储库外部文件的想法相同,您可以保存您想要的更改,删除存储中不需要的更改,然后重新应用您移动的更改。 但是,我使用git stash作为“某处”(结果,最后还有一个额外的步骤:删除你放在藏匿处的cahnges,因为你也将它们移开了)。


将以下代码保存到文件中,例如,名为stash 。 用法是stash <filename_regex> 。 参数是文件完整路径的正则表达式。 例如,要存储a / b / c.txt, stash a/b/c.txtstash .*/c.txt等。

$ chmod +x stash
$ stash .*.xml
$ stash xyz.xml

要复制到文件中的代码:

#! /usr/bin/expect --
log_user 0
set filename_regexp [lindex $argv 0]

spawn git stash -p

for {} 1 {} {
  expect {
    -re "diff --git a/($filename_regexp) " {
      set filename $expect_out(1,string)
    }
    "diff --git a/" {
      set filename ""
    }
    "Stash this hunk " {
      if {$filename == ""} {
        send "n\n"
      } else {
        send "a\n"
        send_user "$filename\n"
      }
    }
    "Stash deletion " {
      send "n\n"
    }
    eof {
      exit
    }
  }
}

git stash -p (或git add -p with stash --keep-index )太麻烦时,我发现使用diffcheckoutapply更容易:

仅“隐藏”特定文件/目录:

git diff path/to/dir > stashed.diff
git checkout path/to/dir

然后是

git apply stashed.diff

我不知道如何在命令行上执行此操作,仅使用SourceTree。 假设您已经更改了文件A,并且在文件B中有两个更改块。如果您只想隐藏文件B中的第二个块并保持其他所有内容不变,请执行以下操作:

  1. 一切都好
  2. 对工作副本执行更改以撤消文件A中的所有更改。(例如,启动外部差异工具并使文件匹配。)
  3. 使文件B看起来好像只对其应用了第二个更改。 (例如,启动外部差异工具并撤消第一次更改。)
  4. 使用“保持暂存更改”创建存储。
  5. 一切都取消
  6. 完成!

我会使用git stash save --patch 。 我没有发现交互性令人讨厌,因为在它期间有选项将所需操作应用于整个文件。


我已经回顾了这个和许多类似线程的答案和评论。 请注意,以下任何命令均无法正确存储任何特定的已跟踪/未跟踪文件

  • git stash -p (--patch) :手动选择帅哥,不包括未跟踪的文件
  • git stash -k (--keep-index) :存储所有被跟踪/未跟踪的文件并将它们保存在工作目录中
  • git stash -u (--include-untracked) :存储所有被跟踪/未跟踪的文件
  • git stash -p (--patch) -u (--include-untracked) :命令无效

目前,能够存储任何特定跟踪/未跟踪文件的最合理方法是:

  • 暂时提交您不想存储的文件
  • 添加并藏匿
  • 弹出临时提交

我在回答另一个问题的过程中为这个过程写了一个简单的脚本,这里有一些步骤可以在SourceTree中执行这个过程 。


更新(2015年2月14日) - 我稍微重写了脚本,以便更好地处理冲突的情况,现在应该将其显示为未合并的冲突而不是.rej文件。

我经常发现做@ bukzor方法的倒数更直观。 也就是说,要进行一些更改,然后只存储那些分阶段的更改。

不幸的是,git没有提供git stash --only-index或类似的东西,所以我掀起了一个脚本来做到这一点。

#!/bin/sh

# first, go to the root of the git repo
cd `git rev-parse --show-toplevel`

# create a commit with only the stuff in staging
INDEXTREE=`git write-tree`
INDEXCOMMIT=`echo "" | git commit-tree $INDEXTREE -p HEAD`

# create a child commit with the changes in the working tree
git add -A
WORKINGTREE=`git write-tree`
WORKINGCOMMIT=`echo "" | git commit-tree $WORKINGTREE -p $INDEXCOMMIT`

# get back to a clean state with no changes, staged or otherwise
git reset -q --hard

# Cherry-pick the index changes back to the index, and stash.
# This cherry-pick is guaranteed to succeed
git cherry-pick -n $INDEXCOMMIT
git stash

# Now cherry-pick the working tree changes. This cherry-pick may fail
# due to conflicts
git cherry-pick -n $WORKINGCOMMIT

CONFLICTS=`git ls-files -u`
if test -z "$CONFLICTS"; then
    # If there are no conflicts, it's safe to reset, so that
    # any previously unstaged changes remain unstaged
    #
    # However, if there are conflicts, then we don't want to reset the files
    # and lose the merge/conflict info.
    git reset -q
fi

您可以将上述脚本保存为路径上某处的git-stash-index ,然后可以将其作为git stash-index调用

# <hack hack hack>
git add <files that you want to stash>
git stash-index

现在,存储包含一个新条目,该条目仅包含您已暂存的更改,并且您的工作树仍包含任何未暂存的更改。

在某些情况下,工作树更改可能取决于索引更改,因此当您隐藏索引更改时,工作树更改会发生冲突。 在这种情况下,您将获得通常使用git merge / git mergetool / etc解决的未合并冲突。


由于git基本上是关于管理所有存储库内容和索引(而不是一个或多个文件),因此git stash交易毫不奇怪, 与所有工作目录

实际上,自Git 2.13(2017年第2季度)以来,您可以使用git stash push存储单个文件:

git stash push [--] [<pathspec>...]

pathspec被赋予' git stash push '时,新的stash仅记录与pathspec匹配的文件的修改状态

有关更多信息,请参阅“存储对特定文件的更改 ”。

测试用例不言自明:

test_expect_success 'stash with multiple pathspec arguments' '
    >foo &&
    >bar &&
    >extra &&
    git add foo bar extra &&

    git stash push -- foo bar &&   

    test_path_is_missing bar &&
    test_path_is_missing foo &&
    test_path_is_file extra &&

    git stash pop &&
    test_path_is_file foo &&
    test_path_is_file bar &&
    test_path_is_file extra

原始答案(下面,2010年6月)是关于手动选择您想藏匿的内容。

Casebash评论:

这个( stash --patch原始解决方案)很不错,但我经常修改了很多文件所以使用补丁很烦人

的answer (upvoted,2011年11月)提出了一个更实际的解决方案,基于
git add + git stash --keep-index
去看看并提出他的答案,这应该是官方的(而不是我的)。

关于该选项, chhh在评论中指出了另一种工作流程:

你应该在这样的藏匿之后“ git reset --soft ”来恢复你的明确阶段:
为了达到原始状态 - 这是一个明确的暂存区域,并且只有一些选择的非阶段性修改,可以轻轻地重置索引以获取(不提交像你这样的东西 - bukzor - 确实)。

(原始答案2010年6月:手动藏匿)

然而, git stash save --patch可以让你实现你所追求的部分git stash save --patch

使用--patch ,您可以交互式地从HEAD和工作树之间的差异中选择要存储的数据。
构建存储条目,使其索引状态与存储库的索引状态相同,并且其工作树仅包含您以交互方式选择的更改。 然后,从您的工作树中回滚所选更改。

但是,这将保存完整索引(可能不是您想要的,因为它可能包括已编入索引的其他文件),以及部分工作树(可能看起来像您要隐藏的那个)。

git stash --patch --no-keep-index

可能更适合。

如果--patch不起作用,手动过程可能会:

对于一个或多个文件,中间解决方案是:

  • 将它们复制到Git仓库之外
    (实际上, eleotlecram提出了一个有趣的选择 )
  • git stash
  • 把它们复制回去
  • git stash #这次,只有你想要的文件被藏起来了
  • git stash pop [email protected]{1} #重新应用所有文件修改
  • git checkout -- afile #在任何本地修改之前将文件重置为HEAD内容

在相当繁琐的过程结束时,您将只有一个或几个文件被藏起来。


由于在Git中创建分支是微不足道的,因此您可以创建一个临时分支并将单个文件检入其中。


要存储单个文件,请使用git stash --patch [file]

这将提示: Stash this hunk [y,n,q,a,d,j,J,g,/,e,?]? ? Stash this hunk [y,n,q,a,d,j,J,g,/,e,?]? ? 。 只需键入a (将这个大块以及所有后来的文件藏在文件中)你就可以了。


这里的每个答案都是如此复杂......

这个“藏匿”怎么样:

git diff /dir/to/file/file_to_stash > /tmp/stash.patch
git checkout -- /dir/to/file/file_to_stash

这将弹出文件更改回:

git apply /tmp/stash.patch

与存储一个文件并将其弹回的完全相同的行为。





git-stash