仅在 git 中存储分阶段更改 - 有可能吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14759748/
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
Stashing only staged changes in git - is it possible?
提问by MrDuk
Is there a way I can stash just my staged changes? The scenario I'm having issues with is when I've worked on several bugs at a given time, and have several unstaged changes. I'd like to be able to stage these files individually, create my .patch files, and stash them away until the code is approved. This way, when it's approved I can stash my entire (current) session, pop that bug and push the code.
有没有办法可以只隐藏我的分阶段更改?我遇到问题的情况是我在给定时间处理了几个错误,并且有几个未分阶段的更改。我希望能够单独暂存这些文件,创建我的 .patch 文件,并将它们隐藏起来,直到代码获得批准。这样,当它获得批准时,我可以隐藏我的整个(当前)会话,弹出该错误并推送代码。
Am I going about this the wrong way? Am I misunderstanding how git can work in other ways to simplify my process?
我会以错误的方式解决这个问题吗?我是否误解了 git 如何以其他方式工作来简化我的过程?
回答by Bart?omiej Semańczyk
Yes, It's possible with DOUBLE STASH
是的,可以使用DOUBLE STASH
- Stage all your files that you need to stash.
- Run
git stash --keep-index
. This command will create a stash with ALLof your changes (staged and unstaged), but will leave the staged changes in your working directory (still in state staged). - Run
git stash push -m "good stash"
- Now your
"good stash"
has ONLY staged files.
- 暂存您需要隐藏的所有文件。
- 运行
git stash --keep-index
。此命令将创建一个包含所有更改(staged 和 unstaged)的存储,但会将已暂存的更改保留在您的工作目录中(仍处于暂存状态)。 - 跑
git stash push -m "good stash"
- 现在你
"good stash"
已经ONLY上演文件。
Now if you need unstaged files before stash, simply apply first stash (the one created with --keep-index
) and now you can remove files you stashed to "good stash"
.
现在,如果你之前藏匿需要不分阶段的文件,简单地套用第一藏匿(与创建的--keep-index
),现在你可以删除你藏起来的文件"good stash"
。
Enjoy
享受
回答by Eugen Konkov
With latest git you may use --patch
option
使用最新的 git,您可以使用--patch
选项
git stash push --patch
git stash save --patch # for older git versions
And git will ask you for each change in your files to add or not into stash.
You just answer y
or n
并且 git 会要求您将文件中的每个更改添加或不添加到存储中。
你只需回答y
或n
UPD
Alias for DOUBLE STASH:
DOUBLE STASH 的UPD
别名:
git config --global alias.stash-staged '!bash -c "git stash --keep-index; git stash push -m "staged" --keep-index; git stash pop stash@{1}"'
Now you can stage your files and then run git stash-staged
.
As result your staged files will be saved into stash.
现在您可以暂存您的文件,然后运行git stash-staged
.
因此,您的暂存文件将保存到 stash 中。
If you do not want to keep staged files and want move them into stash. Then you can add another alias and run git move-staged
:
如果您不想保留暂存文件并希望将它们移动到 stash 中。然后你可以添加另一个别名并运行git move-staged
:
git config --global alias.move-staged '!bash -c "git stash-staged;git commit -m "temp"; git stash; git reset --hard HEAD^; git stash pop"'
回答by Joe
I made a script that stashes only what is currently staged and leaves everything else. This is awesome when I start making too many unrelated changes. Simply stage what isn't related to the desired commit and stash just that.
我制作了一个脚本,只存储当前上演的内容并保留其他所有内容。当我开始进行太多不相关的更改时,这很棒。只需暂存与所需提交无关的内容,然后将其隐藏即可。
(Thanks to Bart?omiej for the starting point)
(感谢 Bart?omiej 的起点)
#!/bin/bash
#Stash everything temporarily. Keep staged files, discard everything else after stashing.
git stash --keep-index
#Stash everything that remains (only the staged files should remain) This is the stash we want to keep, so give it a name.
git stash save ""
#Apply the original stash to get us back to where we started.
git stash apply stash@{1}
#Create a temporary patch to reverse the originally staged changes and apply it
git stash show -p | git apply -R
#Delete the temporary stash
git stash drop stash@{1}
回答by Somo S.
TL;DRJust add
-- $(git diff --staged --name-only)
for your git<pathspec>
parameter
TL;DR只需
-- $(git diff --staged --name-only)
为您的 git<pathspec>
参数添加
Here is a simple one-liner:
这是一个简单的单行:
git stash -- $(git diff --staged --name-only)
And to add a message simply:
并简单地添加一条消息:
git stash push -m "My work in progress" -- $(git diff --staged --name-only)
Tested on v2.17.1and v2.21.0.windows.1
Limitations:
- Please be aware that this will stash every single thing, if you have no files staged.
- Also if you have a file that is only partially staged ( i.e. only some changed lines, are staged while some other changed lines are not), then the whole file will get stashed (including unstaged lines).
在v2.17.1和v2.21.0.windows.1上测试
限制:
- 请注意,如果您没有暂存文件,这将隐藏所有内容。
- 此外,如果您有一个仅部分暂存的文件(即只有一些已更改的行已暂存,而其他一些已更改的行未暂存),则整个文件将被隐藏(包括未暂存的行)。
回答by Michael
To accomplish the same thing...
为了完成同样的事情......
- Stage just the files you want to work on.
git commit -m 'temp'
git add .
git stash
git reset HEAD~1
- 仅暂存您要处理的文件。
git commit -m 'temp'
git add .
git stash
git reset HEAD~1
Boom. The files you don't want are stashed. The files you want are all ready for you.
繁荣。你不想要的文件被藏起来了。你想要的文件都为你准备好了。
回答by Shamps
In this scenario, I prefer to create new branches for each issue. I use a prefix temp/ so I know that I can delete these branches later.
在这种情况下,我更喜欢为每个问题创建新分支。我使用前缀 temp/ 所以我知道我可以稍后删除这些分支。
git checkout -b temp/bug1
Stage the files that fix bug1 and commit them.
暂存修复 bug1 的文件并提交它们。
git checkout -b temp/bug2
You can then cherry pick the commits from the respective branches as require and submit a pull request.
然后,您可以根据需要从各自的分支中挑选提交并提交拉取请求。
回答by knittl
Why don't you commit the change for a certain bug and create a patch from that commit and its predecessor?
为什么不针对某个错误提交更改并从该提交及其前身创建补丁?
# hackhackhack, fix two unrelated bugs
git add -p # add hunks of first bug
git commit -m 'fix bug #123' # create commit #1
git add -p # add hunks of second bug
git commit -m 'fix bug #321' # create commit #2
Then, to create the appropriate patches, use git format-patch
:
然后,要创建适当的补丁,请使用git format-patch
:
git format-patch HEAD^^
This will create two files: 0001-fix-bug-123.patch
and 0002-fix-bug-321.patch
这将创建两个文件:0001-fix-bug-123.patch
和0002-fix-bug-321.patch
Or you can create separate branches for each bug, so you can merge or rebase bug fixes individually, or even delete them, if they don't work out.
或者您可以为每个错误创建单独的分支,这样您就可以单独合并或重新调整错误修复,如果它们不起作用,甚至可以删除它们。
回答by VonC
git stash --keep-index
is a good solution... except it did not work correctly on paths that have been removed, which has been fixed in Git 2.23 (Q3 2019)
git stash --keep-index
是一个很好的解决方案......除了它在已删除的路径上无法正常工作,这已在 Git 2.23(2019 年第 3 季度)中修复
See commit b932f6a(16 Jul 2019) by Thomas Gummerer (tgummerer
).
(Merged by Junio C Hamano -- gitster
--in commit f8aee85, 25 Jul 2019)
请参阅Thomas Gummerer ( ) 的提交 b932f6a(2019 年 7 月 16 日)。(由Junio C Hamano合并-- --在提交 f8aee85 中,2019 年 7 月 25 日)tgummerer
gitster
stash
: fix handling removed files with--keep-index
git stash push --keep-index
is supposed to keep all changes that have been added to the index, both in the index and on disk.Currently this doesn't behave correctly when a file is removed from the index.
Instead of keeping it deleted on disk, **--keep-indexcurrently restores the file.**Fix that behaviour by using '
git checkout
' in no-overlay mode which can faithfully restore the index and working tree.
This also simplifies the code.Note that this will overwrite untracked files if the untracked file has the same name as a file that has been deleted in the index.
stash
:修复处理已删除的文件--keep-index
git stash push --keep-index
应该保留已添加到索引中的所有更改,无论是在索引中还是在磁盘上。当前,当从索引中删除文件时,这行为不正确。
**--keep-index当前恢复文件,而不是将其保留在磁盘上。**通过
git checkout
在无覆盖模式下使用“ ”来修复该行为,这可以忠实地恢复索引和工作树。
这也简化了代码。请注意,如果未跟踪文件与索引中已删除的文件同名,这将覆盖未跟踪文件。
回答by Raman
Stashing just the index (staged changes) in Git is more difficult than it should be. I've found @Joe's answerto work well, and turned a minor variation of it into this alias:
在 Git 中仅存储索引(分阶段更改)比应有的更困难。我发现@Joe 的答案效果很好,并将它的一个小变化变成了这个别名:
stash-index = "!f() { \
git stash push --quiet --keep-index -m \"temp for stash-index\" && \
git stash push \"$@\" && \
git stash pop --quiet stash@{1} && \
git stash show -p | git apply -R; }; f"
It pushes boththe staged and unstaged changes into a temporary stash, leaving the staged changes alone. It then pushes the staged changes into the stash, which is the stash we want to keep. Arguments passed to the alias, such as --message "whatever"
will be added to this stash command. Finally, it pops the temporary stash to restore the original state and remove the temporary stash, and then finally "removes" the stashed changes from the working directory via a reverse patch application.
这必将推动双方的演出和未分级变成一个临时藏匿处,留下独自上演的变化。然后它将分阶段的更改推送到 stash,这是我们想要保留的 stash。传递给别名的参数,例如--message "whatever"
将添加到此 stash 命令中。最后,它弹出临时存储以恢复原始状态并删除临时存储,然后最后通过反向补丁应用程序从工作目录中“删除”隐藏的更改。
For the opposite problem of stashing just the unstaged changes (alias stash-working
) see this answer.
对于仅存储未暂存更改(别名stash-working
)的相反问题,请参阅此答案。
回答by Mike Monkiewicz
Is it absolutely necessary to work on several bugs at once? And by "at once," I mean "having files edited for multiple bugs at the same time." Because unless you absolutely need that, I'd only work on one bug at a time in your environment. That way you can use local branches & rebase, which I find far easier than managing a complex stash/stage.
一次处理多个错误是否绝对有必要?“同时”是指“同时为多个错误编辑文件”。因为除非您绝对需要,否则我一次只会处理您环境中的一个错误。这样你就可以使用本地分支和变基,我发现这比管理复杂的存储/阶段容易得多。
Let's say master is at commit B. Now work on bug #1.
假设 master 处于提交 B。现在处理错误 #1。
git checkout -b bug1
Now you're on branch bug1. Make some changes, commit, wait for code review. This is local, so you're not affecting anyone else, and it should be easy enough to make a patch from git diffs.
现在你在分支 bug1 上。进行一些更改,提交,等待代码。这是本地的,因此您不会影响其他任何人,并且从 git diffs 制作补丁应该很容易。
A-B < master
\
C < bug1
Now you're working on bug2. Go backto master with git checkout master
. Make a new branch, git checkout -b bug2
. Make changes, commit, wait for code review.
现在您正在处理 bug2。去背到主用git checkout master
。创建一个新分支,git checkout -b bug2
。进行更改,提交,等待代码。
D < bug2
/
A-B < master
\
C < bug1
Let's pretend that someone else commits E & F on master while you're waiting on review.
让我们假设在您等待时其他人在 master 上提交了 E&F。
D < bug2
/
A-B-E-F < master
\
C < bug1
When your code has been approved, you can rebase it on to master with the following steps:
当您的代码获得批准后,您可以通过以下步骤将其重新设置为 master:
git checkout bug1
git rebase master
git checkout master
git merge bug1
This will result in the following:
这将导致以下结果:
D < bug2
/
A-B-E-F-C' < master, bug1
Then you can push, delete your local bug1 branch, and off you go. One bug at a time in your workspace, but with using local branches your repository can handle multiple bugs. And this avoids a complicated stage/stash dance.
然后你可以推送,删除你本地的 bug1 分支,然后就可以了。在您的工作区中一次一个错误,但通过使用本地分支,您的存储库可以处理多个错误。这避免了复杂的舞台/隐藏舞蹈。
Answer to ctote's question in the comments:
在评论中回答 ctote 的问题:
Well, you can go back to stashing for each bug, and only work with one bug at a time. Atleast that saves you the staging issue. But having tried this, I personally find it troublesome. Stashes are a bit messy in a git log graph. And more importantly, if you screw something up you can't revert. If you have a dirty working directory and you pop a stash, you can't "undo" that pop. It's much harder to screw up already existing commits.
好吧,您可以返回对每个错误进行存储,并且一次只处理一个错误。至少可以为您节省分期问题。但是试过这个,我个人觉得很麻烦。在 git log 图中,stash 有点混乱。更重要的是,如果你把事情搞砸了,你就无法恢复。如果您有一个脏的工作目录并且您弹出一个存储,则无法“撤消”该弹出。搞砸已经存在的提交要困难得多。
So git rebase -i
.
所以git rebase -i
。
When you rebase one branch onto another, you can do it interactively (the -i flag). When you do this, you have the option to pick what you want to do with each commit. Pro Git is an awesome book which is also online in HTML format, and has a nice section on rebasing & squashing:
当您将一个分支变基到另一个分支时,您可以交互地进行(-i 标志)。执行此操作时,您可以选择对每次提交执行的操作。Pro Git 是一本很棒的书,它也以 HTML 格式在线提供,并且有一个关于变基和压缩的很好的部分:
http://git-scm.com/book/ch6-4.html
http://git-scm.com/book/ch6-4.html
I'll steal their example verbatim for convenience. Pretend you have the following commit history, and you want to rebase & squash bug1 onto master:
为方便起见,我将逐字窃取他们的示例。假设您有以下提交历史记录,并且您想将 bug1 变基并压缩到 master 上:
F < bug2
/
A-B-G-H < master
\
C-D-E < bug1
Here's what you will see when you type git rebase -i master bug1
这是您键入时会看到的内容 git rebase -i master bug1
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
#
# Commands:
# p, pick = use commit
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
To squash all commits of a branch down into a single commit, keep the first commit as "pick" and replace all subsequent "pick" entries with "squash" or simply "s". You will get the opportunity to change the commit message, too.
要将分支的所有提交压缩为单个提交,请将第一个提交保留为“pick”,并将所有后续的“pick”条目替换为“squash”或简单的“s”。您也将有机会更改提交消息。
pick f7f3f6d changed my name a bit
s 310154e updated README formatting and added blame
s a5f4a0d added cat-file
#
# Commands:
# p, pick = use commit
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
So yeah, squashing is a bit of a pain, but I would still recommend it over heavy use of stashes.
所以是的,挤压有点痛苦,但我仍然会推荐它而不是大量使用隐藏。