git 您如何仅存储已添加的文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30359921/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 11:01:53  来源:igfitidea点击:

How do you stash only files that have been added?

gitgit-stash

提问by peter-b

For example, a git statusgives the following:

例如,agit status给出以下内容:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   app/src/[....]
    modified:   app/src/[....]
    new file:   app/src/[....]
    deleted:    app/src/[....]
    modified:   app/src/[....]
    modified:   test/unit/[....]
    modified:   test/unit/[....]
    new file:   test/unit/[....]
    deleted:    test/unit/[....]
    modified:   test/unit/[....]

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   test/unit/[....]

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    app/src/[....]/
    app/src/[....]/
    app/src/[....]/

(I have blanked the filenames)

(我已经清空了文件名)

How would I stash just the changes I have git added (i.e. "Changes to be committed", not unstaged changes or untracked files) so I can transfer them to another branch instead?

我将如何仅存储我已git add编辑的更改(即“要提交的更改”,而不是未暂存的更改或未跟踪的文件),以便我可以将它们转移到另一个分支?

回答by torek

Git's basic storage mechanism is "the commit"—in fact, all git stashdoes is make a couple of somewhat unusual commits—so Nick Volynkin's answeris a correct one. It could perhaps use a bit of expansion though, and there are easier (well, potentially easier) methods.

Git 的基本存储机制是“提交”——事实上,git stash所做的只是进行一些不寻常的提交——所以Nick Volynkin 的答案是正确的。不过,它可能会使用一些扩展,并且有更简单(好吧,可能更简单)的方法。

I'm not a very big fan of git stash, but if you're used to using it, here's the simplest of the other methods:

我不是 的忠实粉丝git stash,但如果您习惯使用它,这里是其他方法中最简单的:

  1. git stash save(aka git stash). This writes two commits, one based on the current index and a second to hold as-yet-unstaged work-tree files. (If you need to hold untrackedfiles, you can add the -uflag, and then the stash script adds yet a third commit. Usually you can just leave these untracked files floating around in your work tree untracked, though.) These commits are not on any branch, they are only on/in the special "stash" ref. Meanwhile you're still on the "wrong" branch, which I'll call wrongbrbelow.

  2. git checkoutthe branch you want these on. Now you're on the right branch.

  3. git stash apply --index. This uses the special stash commits made in step 1, while also leaving them there (apply) in the stash. The --indexis very important: it tells the stash script to keep the index and unstaged files separate, i.e., give you back the staged and unstaged setup you had earlier.

    If all goes well, you're now in a position to git committhe changes to the branch you want them on. The previously staged files are again staged, and the unstaged files are still unstaged, because you apply-ed the stash with --index. The commit will commit the staged files, leaving the unstaged files unstaged.

  4. Now you can get back on the other "wrong" branch (where you made the stash initially) and git stash applyor git stash popwith or without --index. You may need to clean out any unstaged files (and it's safe to do so, they are still in the stash): git reset --hard, followed by git checkout wrongbr, then git stash pop. Note that popis just applyfollowed by drop: we didn't wantto dropthe stash in step 3 (the stash has the only copy of the original modified-but-unstaged files), which is why we used applythere, but now we (presumably) dowant to drop the stash, so using popis OK.

  1. git stash save(又名git stash)。这会写入两次提交,一次基于当前索引,另一次用于保存尚未暂存的工作树文件。(如果您需要保留未跟踪的文件,您可以添加-u标志,然后存储脚本添加第三次提交。不过,通常您可以让这些未跟踪的文件在您的工作树中浮动而不被跟踪。)这些提交未开启任何分支,它们都只在/在特殊的“藏匿”参考中。与此同时,你仍然在“错误”的分支上,我将wrongbr在下面称之为。

  2. git checkout你想要这些的分支。现在你在正确的分支上。

  3. git stash apply --index. 这将使用在步骤 1 中进行的特殊存储提交,同时还将它们留在 ( apply) 存储中。这--index非常重要:它告诉 stash 脚本将索引和未暂存文件分开,即,返回您之前的暂存和未暂存设置。

    如果一切顺利,您现在就git commit可以对您希望它们所在的分支进行更改。先前暂存的文件再次暂存,而未暂存的文件仍然未暂存,因为您apply使用--index. 提交将提交暂存文件,使未暂存文件保持未暂存状态。

  4. 现在你可以回到另一个“错误”的分支(你最初在那里制作藏匿处),git stash apply或者git stash pop有或没有--index. 您可能需要清除任何未暂存的文件(这样做是安全的,它们仍在存储中): git reset --hard,然后是git checkout wrongbr,然后是git stash pop。请注意,pop只是apply后面drop:我们不希望下降步骤3中的藏匿处(藏匿有只有原来的修改,但是,不分阶段的文件复制),这就是为什么我们使用apply那里,但现在我们(大概)确实想放下藏匿处,所以使用pop是可以的。

There's a big potential pitfall in step 3, though: it's possible the stash won't apply correctly. If so, you mustuse some other method. This is one reason I don't really like the stashsystem: it falls down in hard cases and leaves you needing to know the tools you can use if you don't use stash. In which case, you can just use those tools most the time ... and then use stashas a convenient short-cut for cases where you're sure it will work.

但是,在第 3 步中存在一个很大的潜在陷阱:可能无法正确应用 stash。如果是这样,您必须使用其他方法。这是我不太喜欢该stash系统的原因之一:它在困难情况下会崩溃,让您需要知道如果您不使用stash. 在这种情况下,您可以在大多数情况下只使用这些工具……然后stash在您确定它会起作用的情况下将其用作方便的捷径。



Background: a commit takes whatever is in the index now—git ls-files --cachedwill show the complete contents, while git statustrims this down to the "interesting" ones and adds additional useful information—and makes a commit out of them, with all the necessary tree objects and so on. The new commit's parent commit is whatever the current commit was before.

背景:提交现在采用索引中的任何git ls-files --cached内容 - 将显示完整的内容,同时将其git status修剪为“有趣”的内容并添加额外的有用信息 - 并使用所有必要的树对象等进行提交在。新提交的父提交是当前提交之前的任何内容。

You want your new commit made on another branch. One way to do this is to make it now, on the current branch; then copy that commit to a new, different commit on a different branch. To do the "copy commit to new, different commit on different branch" you can use git cherry-pick. It's true that you can use git rebase: under the covers, it uses git cherry-pickitself. But rebaseis not quite the right tool: it's designed for en-masse cherry-picking, and you have just one commit; and at the end it uses git resetto move a branch label, but not quite in the way you want. You can make it work, but there are some more appropriate tools.

您希望在另一个分支上进行新提交。一种方法是现在就在当前分支上创建它;然后将该提交复制到不同分支上的新的不同提交。要执行“将提交复制到不同分支上的新的不同提交”,您可以使用git cherry-pick. 确实,您可以使用git rebase: 在幕后,它使用git cherry-pick自身。但rebase它并不是一个合适的工具:它是为大量采摘樱桃而设计的,而且你只有一次提交;最后它git reset用来移动一个分支标签,但不是你想要的方式。你可以让它工作,但有一些更合适的工具。

Let's go back to the original problem though: you want to take the current index and use it to make a new commit, but on another branch. This would be easiest if you could just switch to the other branch now, without doing anything else, and then make the new commit.

让我们回到最初的问题:您想获取当前索引并使用它来进行新的提交,但是在另一个分支上。如果您现在可以切换到另一个分支而不做任何其他事情,然后进行新的提交,这将是最简单的。

Chances are good that you cando this. Just git checkout otherbranchand then git commit. There are three possible cases here:

您很有可能做到这一点。只是git checkout otherbranch然后git commit。这里有三种可能的情况:

  1. The other branch doesn't exist yet. Great! Use git checkout -b newbranchto create it, starting from where you are now. Then git commit. You're done, unless you want to rebase the new branch to start from somewhere other than "where you are now". If so, use git rebaseon the new branch. Note that you can do that rebase later, after you've taken care of the unstaged files.

  2. The other branch does exist, and—lucky you—git checkout otherbranchworks fine. Do that and commit, and you're done. You can then git checkoutwhatever branch you want for the unstaged files.

  3. The most annoying case: the other branch does exist, but git checkouttells you that you'll overwrite something that you haven't committed.

  1. 另一个分支还不存在。伟大的!使用git checkout -b newbranch来创建它,从你现在在哪里开始。然后git commit。大功告成,除非您想将新分支变基以从“您现在所在的位置”以外的其他地方开始。如果是这样,请git rebase在新分支上使用。请注意,您可以在处理未暂存的文件后进行该变基。

  2. 另一个分支确实存在,而且——幸运的是——git checkout otherbranch工作正常。这样做并提交,你就完成了。然后,您可以git checkout为未暂存文件提供任何您想要的分支。

  3. 最烦人的情况:另一个分支确实存在,但git checkout告诉您将覆盖您尚未提交的内容。

Case 3 is the one where you need to commit-or-stash.

第 3 种情况是您需要提交或存储的情况。

What to do here depends on what you are most comfortable with. You can, for instance, try the four-step stashmethod described above as the simplest alternative.

在这里做什么取决于您对什么最满意。例如,您可以尝试将上述四步法stash作为最简单的替代方法。

For myself, though, I would just commit now, on the "wrong" branch, then commit again (or use git stash) to get the unstaged files out of the way. This gives me a commit I can git cherry-pickinto the rightbranch. Here's an example sequence that's likely to work:

不过,对我自己而言,我现在只会在“错误”分支上提交,然后再次提交(或使用git stash)来清除未暂存的文件。这给了我一个可以git cherry-pick进入正确分支的提交。这是一个可能有效的示例序列:

  1. git committo make the commit, but on the "wrong" branch (let's call your current branch wrongbrfor reference below).
  2. git stash saveto save the unstaged changes (or, with -u, untracked files too).
  3. git checkoutthe branch you want the commit to have been on, e.g., git checkout rightbr.
  4. git cherry-pick wrongbr. If this succeeds, good; if not, edit files as needed to clean up after the merge issues, then git committhe result.
  5. git checkout wrongbr: we will now fix this up by removing the commit copied in step 4.
  6. git reset --hard HEAD^: this drops the commit that we copied.
  7. git stash pop(or git stash apply && git stash dropwhich does the same thing, the applyvariant simply giving you the opportunity to inspect the result before you dropthe stash).
  1. git commit进行提交,但在“错误”分支上(让我们在下面调用您当前的分支wrongbr以供参考)。
  2. git stash save保存未暂存的更改(或者,也可以保存-u未跟踪的文件)。
  3. git checkout您希望提交所在的分支,例如,git checkout rightbr
  4. git cherry-pick wrongbr. 如果这成功了,很好;如果没有,在合并问题后根据需要编辑文件进行清理,然后git commit是结果。
  5. git checkout wrongbr:我们现在将通过删除在步骤 4 中复制的提交来解决这个问题。
  6. git reset --hard HEAD^:这会删除我们复制的提交。
  7. git stash pop(或者git stash apply && git stash drop做同样的事情,apply变体只是让你有机会在你drop藏匿之前检查结果)。

Note step 4 here: git cherry-picktakes the named commit (the tip of wrongbr, which contains the commit-we-want that's simply on the wrong branch), compares it with its parent, and then attempts to apply the resulting diff to the current branch. This may need to do a 3-way merge, if the files in the current branch differ a lot from their corresponding files in wrongbr. This is the same place the complications occur in the simple case of just checking out rightbrand committing initially. That is, we're doing this long version because the "most annoying" case occurred when we tried to just git checkout rightbrbefore committing, so there's a good chance we need to do some fixing-up. This is also likely to cause problems with the original 4-step stashmethod.

注意这里的第 4 步:git cherry-pick获取命名提交( 的尖端wrongbr,它包含我们想要的提交,只是在错误的分支上),将它与其父级进行比较,然后尝试将结果差异应用到当前分支。如果当前分支中的文件与其对应的wrongbr. 这与在rightbr最初检查和提交的简单情况下出现并发症的地方相同。也就是说,我们正在做这个长版本,因为“最烦人”的情况发生在我们git checkout rightbr在提交之前尝试时,所以很有可能我们需要做一些修复。这也可能会导致原始 4 步法出现问题stash

回答by Nick Volynkin

Commit those files and then rebase the commit.

提交这些文件,然后重新提交。

回答by kilogic

  1. Stash everything, but keep the index (This stash will have staged (from git add) and non-staged edits):

    git stash --keep-index

  2. Stash the index, which is all that is left after the stash in step 1 (This is what you wanted to stash).

    git stash

  3. Pop or apply (safer) the stash that had it all, the one from step 1 (now in stash@{1}because the newest one is always stash@{0}).

    git stash apply stash@{1}

  4. Restore the files that were originally added to the index, the ones in stash@{0}, by checking them out from the HEAD

    git checkout HEAD ./path/to/files/to/reset ./another/path/to/other/file/to/reset

  5. If you mess up in step 4, try git reset HEAD --hardto wipe out all the local changes and start again at step 3.

  1. 存储所有内容,但保留索引(此存储将已上演(来自git add)和非上演编辑):

    git stash --keep-index

  2. 存储索引,这是在步骤 1 中存储之后剩下的所有内容(这就是您想要存储的内容)。

    git stash

  3. 弹出或应用(更安全)包含所有内容的存储库,即第 1 步中的存储库(现在在,stash@{1}因为最新的始终是stash@{0})。

    git stash apply stash@{1}

  4. 在恢复原先添加到索引中的文件,那些stash@{0},从检查出来HEAD

    git checkout HEAD ./path/to/files/to/reset ./another/path/to/other/file/to/reset

  5. 如果您在第 4 步中搞砸了,请尝试git reset HEAD --hard清除所有本地更改,然后从第 3 步重新开始。