简体   繁体   English

当我将提交推送到远程存储库时,为什么Git会显示本地的“从远程拉出”?

[英]Why does Git show my local “pull from remote” when I push my commit to the remote repo?

So I am having a little trouble understanding Git. 所以我在理解Git时遇到了一些麻烦。 I'm using it on Windows, with a remote (GitLab installed) repo. 我在Windows上使用它,并带有远程(已安装GitLab)仓库。 I have a local copy of the master branch, and I am fairly diligent about using git pull frequently to keep my local copy up-to-date. 我有master分支的本地副本,并且我非常勤奋地频繁使用git pull来使本地副本保持最新。

So it's release time (of course...isn't that when this happens?) and I want to check in the ONE file I've changed. 所以是发布时间了(当然...这不是什么时候发生吗?),我想签入我已更改的一个文件。 I type a git pull but get an error: 我输入git pull但收到错误:

error: Your local changes to the following files would be overwritten by merge:
        <path>/filename.py
Please, commit your changes or stash them before you can merge.
Aborting

I use git diff and sure enough, another developer fixed a typo in the same spot where I'm trying to commit. 我使用git diff ,果然,另一位开发人员在我要提交的位置修复了一个错字。 A quick git status reveals: 快速的git status显示:

Your branch is behind 'origin/master' by 4 commits, and can be fast-forwarded

So, at a loss, I commit my changes to my local repo. 因此,不知所措,我将更改提交给本地存储库。

git add <filename>
git commit -m "reworking to ignore logs"

Now, I can git pull successfully. 现在,我可以git pull成功了。

git pull origin master 
...
Merge made by the 'recursive' strategy
file1
file2...
....
<filename>
5 files changed, 1 insertion, 63 deletions...

Now, I'm able to push my change up to the remote repo 现在,我可以将更改推送到远程仓库

git push

BUT: here's my question. 但是:这是我的问题。 On the remote server, it shows BOTH my commit AND the file changes caused by my local pull after my commit. 在远程服务器上,它既显示我的提交,又显示由我提交后本地pull引起的文件更改。 That is to say, it basically shows that the remote files changed, but in fact changed to what wass ALREADY in the remote repository. 也就是说,它基本上表明,远程文件改变了,但实际上改变了什么沃斯已经在远程仓库。

My boss calls in a panic, asking me why I changed all those (other four) files, and I'm not able to answer. 我的老板惊慌失措,问我为什么我更改了所有(其他四个)文件,而我却无法回答。 We end up checking out the two commits (current and pre-my-changes) and diffing them, to prove that it was ONLY my one file's change is what is different, before we both breathe a sigh of relief. 我们最终检查了两个提交(当前更改和我之前的更改)并进行了比较,以证明在我俩都松了一口气之前,只有我一个文件的更改有所不同。

So my question is: what am I missing? 所以我的问题是:我想念什么? Why should Git think that I want to see that I changed files to match the remote HEAD, in the remote? 为什么Git认为我想看到我更改了文件以匹配远程中的HEAD? I have seen this question about git squash ing , and realize that there is a git rebase which may help me, too. 我已经看到了有关git squash ing的问题 ,并且意识到有一个git rebase也可能对我有帮助。 Can someone help me understand why Git does this? 有人可以帮我理解为什么Git这样做吗? I just feel as though I am not totally embracing the "distributed" paradigm shift. 我只是觉得好像我不完全接受“分布式”范式转换。

Apparently both you and your boss are missing the same thing, and your boss tends towards panic. 显然,您您的老板都错过了同一件事,而您的老板容易陷入恐慌。 :-) :-)

Here's what you did, in graphical form drawn as commits. 这就是您所做的工作,以图形形式绘制为提交。 Originally you had this in your repo: 最初,您的回购中包含以下内容:

... - F - G    <-- HEAD=master, origin/master

where G is the then-latest version. 其中G是当时的最新版本。 But there's a typo in one file, so you edited that file in your work-tree, fixing the problem. 但是一个文件中有一个拼写错误,因此您在工作树中编辑了该文件,从而解决了该问题。 (I'm going to name the file typo just for convenience below.) (为方便起见,我将在此命名文件typo 。)

$ vim typo
...

You haven't committed this yet, but you did change it. 您尚未提交此操作,但您确实进行了更改。 Then you did: 然后您做了:

$ git pull

which got you that error message. 这给你那条错误信息。

Now, behind the scenes, as it were, git pull is just git fetch followed by git merge . 现在,在幕后, git pull只是git fetch然后是git merge So let's look at what git fetch did. 因此,让我们看看git fetch做了什么。 It seems that other developers made four commits; 似乎其他开发人员进行了四次提交。 let's draw them into the graphical representation of the commit-tree: 让我们将它们绘制到提交树的图形表示中:

              H - I - J - K      <-- origin/master
            /
... - F - G                      <-- HEAD=master

The git merge failed because someone else modified file typo too. git merge失败,因为其他人也修改了文件typo

So, now you do: 因此,现在您可以:

$ git add typo
$ git commit -m "reworking to ignore logs"

This adds a new commit on your current branch (whatever HEAD points to), which is obviously master . 这会在当前分支(无论HEAD指向什么)上添加一个新提交,显然是master This gives a commit tree that looks like this: 这给出了一个提交树,如下所示:

              H - I - J - K      <-- origin/master
            /
... - F - G ------------- L      <-- HEAD=master

Now you run git pull again, which again is just fetch followed by merge . 现在,您再次运行git pull ,再次是fetch然后是merge The fetch has nothing to fetch this time (commits H through K , and the label origin/master , are already all taken care of). 这次没有什么可获取的(提交HK ,并且标签origin/master都已经处理了)。 The merge then merges commit K ( origin/master ) into your current branch, master , creating a new merge commit M : 然后合并将提交Korigin/master )合并到当前分支master ,从而创建一个新的合并提交M

              H - I - J - K      <-- origin/master
            /               \
... - F - G ------------- L - M  <-- HEAD=master

If you now git push the result, commit M goes in, merging your change, L , as the first parent of the merge, and their commit K as the second parent. 如果现在使用git push结果,则提交M进入,将更改L合并为合并的第一个父级,将提交K合并为第二个父级。

That's the actual history of what happened to produce M (as hobbs noted in comment) and is perfectly normal. 那就是产生M的真实历史(正如霍布斯在评论中指出的那样),这完全正常。 However, you (and your panicky boss) might prefer to construct a different history, that pretends you noticed the problem in typo after you picked up commits H through K . 然而,你(和你的老板恐慌)可能希望构建一个不同的历史,是假装你注意到这个问题typo你拿起提交 H通过K To do that, you'd "rebase" your commit ( L , above) to sit on top of origin/master . 为此,您需要将提交(在上方的L )“变基”为位于origin/master之上。

You can do this with git pull --rebase (as in hobbs' answer that appeared while I was typing up this long one), or with plain old git rebase after doing a git fetch . 您可以使用git pull --rebase来完成此git pull --rebase (就像我在键入这么长的内容时出现的git pull --rebase 的回答中那样),或者使用git fetch之后的普通旧git rebase进行此操作。 In this case, what you will do is make a copy of the changes in commit L (people often spell this "commit L' "): 在这种情况下,您要做的就是复制 commit L中的更改(人们通常将其拼写为“ commit L' ”):

              H - I - J - K - L'
            /
... - F - G ------------- L

At this point, you don't need commit L any more—it will stick around in the repo for 90 days or so because of git's "reflogs", but it will vanish from normal git log output, for instance—so you just need to re-draw this graph a bit, leaving out the line going to L , and stick the labels on like so: 在这一点上,你不需要提交L更多,它会坚持围绕在回购,因为Git的“reflogs” 90天左右的时间,但它会从正常消失git log输出,例如,所以你只需要重新绘制该图形,省略去往L的线,并像这样粘贴标签:

              H - I - J - K      <-- origin/master
            /               \
... - F - G                   L' <-- HEAD=master

and this is exactly what the git rebase in the command-sequence: 而这正是git rebase在命令序列中重新设置的内容:

$ git add typo
$ git commit -m "reworking to ignore logs"
$ git rebase

would have done. 会做。 (Or, again, you can commit and then use git pull --rebase , which just makes git use the fetch -then- rebase sequence, instead of fetch -then- merge . If there's nothing to fetch, as in this case, that's the same as just running git rebase .) (或者再次,您可以提交,然后使用git pull --rebase ,它只是使git使用fetch -then- rebase序列,而不是fetch -then- merge 。如果没有要提取的内容,在这种情况下,这就是与只运行git rebase相同。)

When you git pull on a branch that has local changes, and there are also upstream changes, the pull will merge the upstream changes into your local changes, creating a merge commit. 当您在具有本地更改的分支上进行git pull时,同时也有上游更改,该pull会将上游更改合并到您的本地更改中,从而创建合并提交。 When you push, this merge commit gets sent to the server and becomes part of the history that you see. 推送时,此合并提交将发送到服务器,并成为您看到的历史记录的一部分。

Two possible things that could help: 可能有两件事可能会有所帮助:

  1. Teach your boss to read the history properly and not freak out about changes that don't actually exist. 教您的老板正确地阅读历史记录,而不是对实际上不存在的更改有所了解。
  2. Use git pull --rebase on feature branches to pull in upstream changes and rebase your unpushed local work on top of them. 在功能分支上使用git pull --rebase上游更改,并在这些更改的基础上重新进行未推送的本地工作。 This results in a cleaner history, and is generally considered an improvement by everyone except anti-history-rewriting purists. 这样可以使历史更清晰,并且除反历史重写的纯粹主义者外,每个人通常都认为这是一种改进。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Git如何通过远程仓库/本地仓库推送和拉动? - How does Git push and pull work with a remote repo/local repo? 我可以将文件添加到本地Git存储库中,但不能将其推送到远程 - Can I add a file to my local Git repo but not push it to remote 为什么我不能将我的本地 Git 存储库推送到我的遥控器? - Why can't I push my local Git repo to my remote? 为什么 git 说当我没有本地更改时我需要推送我的提交,然后执行 git 拉取? - Why does git say I need to push my commit when I have no local changes and then do a git pull? 从远程Git存储库中提取更改并将我的分支提交到远程仓库 - Pull changes from remote Git repository and commit my branch to the remote repo 如何从git中删除从远程仓库中删除和忽略的本地文件? - How can I prevent my local files, which are deleted and ignored in remote repo, being deleted when pull from git? 为什么我的git远程存储库尝试从/ home / git目录下推/拉? - Why does my git remote repository try to push/pull from /home/git directory? 无法将我的本地git存储库推送到远程存储库 - unable to push my local git repo to the remote repo 当我从远程存储库中取出时,为什么Git会返回这些字符? - Why does Git returns these characters when I pull from my remote repository? git 有时在我的本地仓库位于远程仓库之后时不显示 - git sometimes does not show when my local repo is behind the remote one
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM