我只是在commit
远程仓库之前手动push
到我的本地仓库。
但更多时候我pull
来获取编码伙伴的更改。
有时我们都在同一个文件上工作并且存在冲突。在这些情况下,他告诉我在git stash
之前git pull
然后在git stash pop
之后做pull
。
但有时这导致git告诉我下次我不能commit
因为我有未合并的文件。这些通常是我本地树中的实验性更改,我不希望push
或stash
。
有几次我需要发送我的工作,结果是远程仓库的中间修订,包括我本地的实验,调试代码等,我从来没有希望发送。我想避免制造这样的混乱。
这是由于.env
修改我的本地回购吗?如果是这样,我该如何避免呢?如果没有,还有什么可能导致它?我是git的总菜鸟,只使用这几个命令。
答案 0 :(得分:2)
Stash
实际在临时框not in your working tree
中提交/保存您的本地更改。
$ git stash
您可以看到藏匿列表 -
$ git stash --list
在进行更改之前,请确保完全隐藏所有不必要/实验性更改。
$ git stash save 'provide stash message' # better give a stash message
$ git stash # see if all the changes are stashed
您也可以apply
存储而不是pop
(如果不想删除它)。您也可以删除存储而不通过git stash drop
应用它(删除#1存储)。
基本上, pop = apply + drop
$ git stash apply stash@{0} # get back the last (#1) stash changes
$ git stash apply stash@{1} # get back the #2 stash changes
答案 1 :(得分:2)
我想在这里首先提到术语 index 与临时区域意思相同,你应该记住三个 >文件版本"活跃"在任何时候:HEAD
版本,索引或&#34;上演&#34;版本和工作树版本。当您第一次运行git checkout <branch>
时,通常会将所有三个版本都匹配起来。任何已提交的版本都是永久性的,与commit一样永久且不可更改:您无法触及当前提交中存储的版本。您可以随时覆盖索引和工作树版本,但正常模式是:
git add
将工作树版本复制回索引。重复步骤2和3直到满意为止;或使用git add --patch
建立一个类似工作树版本的索引版本,但不同。 (通常一个人这样做是为了制作某个文件的可提交版本,在运行调试版本时,它没有额外的调试内容。)这确实意味着索引和工作树可以彼此不同HEAD提交的<和em>。
如果您运行git commit
,则会从索引/暂存区域中的任何内容进行提交,然后。这就是为什么你必须始终保持git add
,从工作树复制到索引。
作为Sajib Khan answered,git stash save
会进行提交。更确切地说,如果git stash save
执行任何(有时它什么都不做,如果没有任何更改),则至少进行两次提交。如果您使用--untracked
或--all
标志,则会进行三次提交。 The git stash
documentation has a small diagram of this under its DISCUSSION section.与文档一样,我们通常会忽略第三次提交。 1
这些提交的不寻常之处在于它们位于 no 分支上。特殊引用名称refs/stash
指向新创建的w
(工作树)提交。它至少有两个父项,一个是HEAD
提交,另一个是i
(索引)提交。使用--untracked
或--all
时,会有第三个父级(我称之为u
)持有额外的未跟踪文件。
除了一个案例 2 之外,我们在这里也忽略了,在i
和{{1}中保存了每个文件的索引和工作树版本之后然后,w
运行git stash save
以使用git reset --hard HEAD
提交中存储的版本替换这些文件的索引和工作树版本。因此,您的工作现在已保存,可以在以后恢复,但在索引(也称为暂存区域)或工作树中不再存在。
1 如果(并且仅当)使用HEAD
或--all
选项来创建第三次提交,Git还会运行--untracked
并使用适当的选项删除存储在第三个父级中的文件。请记住这一点:任何现有的未跟踪文件(无论是否被忽略)都从不包含在git clean
或i
中。除非您使用这些额外选项,否则它们不保存,因此也不会被清除。请注意,未跟踪文件的定义只是任何不在索引现在 中的文件。最后两个词也很重要,如果你还没有遇到,但最终可能会遇到。
2 使用w
选项时会出现一种情况。在这种情况下,--keep-index
代码做了一些相当棘手的事情:在进行git stash save
和i
提交后,而不是将索引和工作树重置为w
,它会重置他们到HEAD
提交中的内容。这样做的目的是安排工作树来保存建议的新提交,以便测试工作树文件的程序可以测试&#34;是否已提交&#34;版本的文件。不过,这里有几个陷阱,但是:请参阅How do I properly git stash/pop in pre-commit hooks to get a clean working tree for tests?
一旦你有一个存储 - 即i
和i
提交保存,你可以大部分安全地运行w
, 3 或更好, git pull
。这将获得其他Git的新提交,让您将Git记住为git fetch
,通过origin
和origin/master
以及origin/develop
记住它们,依此类推。然后,origin/feature/tall
的第二步,即pull
或rebase
,将重新绑定 - 即,如果您有任何提交,则复制您现有的提交,或者如果您有任何提交,则合并您现有的提交,在/带有您带来的最新提交,并调整您自己的当前分支以指向结果。
到目前为止,一切都进展顺利,正是你正在做的事情。但现在我们遇到了棘手的问题。
现在您正在运行merge
,正如您的同事/编码合作伙伴所建议的那样。我建议从git stash pop
而不是git stash apply
开始,但是当它失败时 - 它失败了,给出了你提到的其他内容 - 这并不重要。 4 无论哪种方式,Git都会尝试应用已保存的提交,以便恢复您在索引和/或工作树中保存的更改。但正如我刚才所说,这很棘手,因为提交是快照,而不是更改。 (另外,默认情况下,git stash pop
/ git stash apply
会抛弃git stash pop
提交。使用i
,它会尝试将--index
提交还原到索引中。)
为了将i
commit 恢复为而不是快照,Git使用其合并机制。存储脚本中包含以下实际行:
w
效果就好像您运行了git merge-recursive $b_tree -- $c_tree $w_tree
- 甚至更近,git merge
- 命令。 Git将您的隐藏工作树git cherry-pick
(提交$w_tree
)与w
(HEAD
)的提交进行比较,以查看&#34;您更改的内容&#34;,以及将您当前的索引转换为针对同一$b_tree
的部分提交($c_tree
),以查看&#34;他们更改了什么&#34;,并合并它们。
与任何合并一样,此合并可能会因合并冲突而失败。这就是你所描述的:
...因为我有未合并的档案而无法拉动......
当合并失败时,它会将部分合并的结果保留在工作树和索引中的原始文件集中。例如,假设文件$b_tree
存在合并冲突。现在代替三个版本的foo.txt
- foo.txt
(当前提交),索引和工作树 - 您有五个版本!这些是:
HEAD
,一如既往; HEAD
获取的版本,这是与您运行时提交的$b_tree
中提交的树一起使用的树HEAD
; git stash save
:当您启动失败的--ours
/ git stash apply
时,这就是索引中的内容。 (这可能与git stash pop
版本匹配。)HEAD
:这是--theirs
中的任何内容,即您隐藏的更改;和请注意,就像使用$w_tree
和git rebase
一样,我们/他们的git cherry-pick
标志在这里有所改变。
一旦你处于这个烦人的&#34;未合并的索引条目&#34;除了完成它或完全中止操作之外,你几乎无能为力。
在这种特殊情况下,git checkout
已经在应用中途停止,因此已经中止了后续的git stash apply
。因此,您仍然拥有您的存储,并可以运行git stash drop
以中止尝试应用存储。或者,您可以编辑工作树文件以完成Git无法执行的合并,并git reset --hard HEAD
将文件复制到索引中,以便索引具有(单个)合并条目工作树,取代三个更高阶段的条目。
这对于任何失败的合并都必须执行相同的过程:您要么中止它,然后找出以后要做什么;或者你现在完成它。
请注意,一般情况下,不应仅仅git add
工作树文件&#34;按照&#34;完成冲突标记。虽然这解决了&#34;不能X,但你有未合并的索引条目&#34;,它会给你留下充满冲突标记的文件,这些标记实际上并没有用。
如果Git需要将某些提交与其他人的提交合并,那么当您运行git add
时,也会发生这类合并失败(合并冲突)。或者,Git可以成功自己进行合并(或者认为它至少成功),然后进行新的合并提交。在这种情况下,系统将提示您输入提交消息:
我注意到
git pull
之后的pull
的副作用有时会打开vi,让我输入提交消息。
这表示您已在分支上进行了正常提交,并且stash
已运行git pull
,它认为它成功合并,现在需要提交此新合并提交的消息
您可能希望在此使用git merge
而不是git rebase
。如果您使用git merge
后跟第二个Git命令,而不是使用git fetch
,则会更容易。
请注意,如果您使用git pull
(并学习它,尤其是非常方便的git rebase
),您可以随意进行各种临时提交,包括:
......本地实验,调试代码等......
当你进行改变时,你会将这些提交复制到另一个人的提交之上,让你的工作成为你自己的工作;你最终可以使用git rebase -i
来&#34;挤压&#34;临时承诺支持一个大决赛&#34;真实&#34;承诺。你必须要小心,不要不小心git rebase -i
他们(一旦你这样做,复制到处都是,并且让其他人放弃它是非常困难的。)
3 我建议不使用git push
:相反,将其拆分为其组成部分。首先,运行git pull
以从另一个Git获取新的提交。一旦你有了提交,如果你愿意,你可以查看它们。然后使用git fetch
或git rebase
将这些提交合并到您的分支中。每个分支需要一个git merge
或git rebase
,但在所有分支之前只需要一个git merge
。
一旦你非常熟悉它将为你工作的两个组成部分如何工作,你就可以安全地运行git fetch
,知道出现问题时 - 最终会发生什么事情 - 你&#39;我会认识到发生了什么以及哪一步失败了,并且会知道如何解决这个问题。
4 但为了完整起见,请注意git pull
仅表示git stash pop
。也就是说,试图应用藏匿处;然后,如果 Git 认为进展顺利,立即放下藏匿处。但有时Git认为它没有问题,但事实并非如此。在这种特殊情况下,仍然可以使用藏匿方式很好,git stash apply && git stash drop
使得它很难恢复。