撤消Git提交并解决拉

时间:2017-02-24 17:49:36

标签: git

我再一次迷失在Git的野外。这一切都发生在Visual Studio 2015的上下文中。

我将一堆文件移动到项目中的新文件夹中。显然,这会丢弃移动文件的所有Git历史记录。我这样说是因为当我对任何移动的文件执行git log --时,它只显示最近的活动,而不是我在几个月内完成的所有活动。

不幸的是,我在同步更改并将当前状态推送到远程存储库后发现了这一点。

我希望将环境恢复到移动所有文件之前的位置,并以不同的方式移动它们(我相信在命令提示符下使用git mv会保留历史记录,这与Visual Studio执行时不同)。

我尝试过:

git reset --hard HEAD~1
从命令行

,将本地文件恢复到我想要的状态。

但是当我回到Visual Studio时,我发现有一个传入的提取待处理。如果我进行任何其他本地更改并尝试提交它们,我会被告知我不能这样做,因为正在等待传入的提取。

我尝试恢复或重置传入的提取。但所有这一切都将我带回到在Visual Studio中移动文件的状态,并且提交历史记录丢失了。

我登录到远程存储库,我可以看到它包含我试图恢复的推送更改。但它们不在活动分支上,我不确定如何在非活动分支上执行git reset

如何摆脱挂起的提取?

其他信息

在完成Schwern的建议时,我发现“失去的历史”实际上已经在我使用的过程的不同阶段丢失了。这就是涉及的内容。

我正在尝试从当前的Git存储库中提取一些文件夹及其历史记录,因此我可以将它们移动到单独的Visual Studio解决方案中。这涉及将本地存储库克隆到一个新文件夹中,将新存储库从其原点中删除,并使用git filter-branch删除除了您尝试提取的内容之外的所有内容。然后,您将提取的内容提取到一个新的Visual Studio解决方案中 - 该解决方案具有自己的独立存储库 - 您可以继续使用。

我之前已经完成了这项工作并保留了历史。但是我今天发现的是,当我做过滤器分支时,历史就消失了:

git filter-branch --subdirectory-filter src/UploadProcessor/extract20170224 -- --all

换句话说,在运行filter-branch之前执行git log会显示我预期的所有历史记录。 filter-branch之后运行git log仅显示文件的最新更改。

思考?除了可能我应该放弃试图保留历史......:)

2 个答案:

答案 0 :(得分:1)

  

我将一堆文件移动到项目中的新文件夹中。显然,这会丢弃移动文件的所有git历史记录。我之所以这么说,是因为当我做一个git log - 在任何移动的文件上它只显示最近的活动,而不是我在几个月内所做的所有事情。

Git没有跟踪重命名,git mvgit rm + a git add。相反,它根据文件的相似性进行猜测,这有其优点和缺点。

你经常需要给予一些鼓励。 git log有多种选择可以做到这一点。 --follow将遵循重命名后的单个文件的历史记录。 -C也会检测副本。 -M将跟随差异中的重命名。 git blame有类似的选择。

  

但是当我回到Visual Studio时,我发现有一个传入的提取待处理。如果我进行任何其他本地更改并尝试提交它们,我会被告知由于挂起的传入提取而无法执行此操作。

我不知道Visual Studio正在做什么,而且我也不知道"等待传入的提取"是或为什么它会被阻止或阻止任何东西。 git fetch始终是安全的。 它只会更新您的远程跟踪分支(即,它会更新您对远程仓库的看法)并且不会触及您的当地分公司。 git pullgit fetch + git merge,有时带有毛茸茸的拉力,可以分两步完成。

怀疑正在发生的事情是Visual Studio正在尝试将Git视为传统的集中版本控制系统(如SVN),并确保您始终致力于提示的分支。在SVN IIRC你必须svn up之前svn commit并且我怀疑Visual Studio正在密码告诉你做什么。因此,在您允许提交之前,必须始终获取并合并最新版本。我怀疑它真的要做git pull,而不是git fetch并且说错了。如果这是您推入的范例,我想就是这样。

这就是为什么我建议避免使用Git GUI进行任何操作,但可视化存储库的状态:谁知道它正在做什么或者他们试图应用什么样的版本控制理念。 Visual Studio可能通过更熟悉的版本控制范例呈现Git来寻求帮助。虽然这可能在短期内有所帮助,但是将Git的方形钉子推入SVN的圆孔只会在不太长的时间内造成问题,因为我怀疑你现在正在经历

无论如何,对于你目前的情况,我认为发生了这件事。

  1. 你犯了错误的改变。
  2. Visual Studio 立即将其推送到远程SVN样式。
  3. 您可以在本地撤消提交。
  4. Visual Studio&#34; helpfully&#34;注意到你在遥控器后面的提交(你自己的提交你刚刚撤消)和SVN风格,除非你赶上你自己的撤消提交,否则不会让你提交任何其他内容。< / LI>

    那就是BTW,这就是为什么你不立即推送Git中的提交。分布式存储库的一半是它将提交与共享分离。因此,您可以在没有共享的情况下随时提交。而且你可以撤消你的错误,因为它们并不是首先分享的。

    因此,假设您的本地仓库有序,git push --force强制存储库与您自己的 匹配,假设没有其他人提交任何其他内容 。事情应该是有序的。

    更安全的事情 是允许fetch / pull发生,获取旧提交,然后以与SVN匹配的传统方式撤消提交作品:使用git revert。这将使一个新的提交反转另一个提交。然后你可以正常推动它。

    考虑不使用Visual Studio来控制Git,或者不使用Git的任何分布式功能。

      

    之前我已经完成了这项工作并保留了历史记录。但是我今天发现的是当我做过滤器分支时历史消失了:

    哦,亲爱的。

    好的,基于对问题的更新,以及git filter-branch已经运行,他们的本地仓库可能处于未知状态。别担心!这只是意味着我无法再预测你的回购邮件是什么样的,我必须看一下它才能确定。

    最好的办法是让它恢复到已知状态。有两种方法可以做到这一点。

    如果您没有git push --force 或以其他方式提交更改(我仍然假设提交后推送Visual Studio)只需克隆新的副本存储库。这会让你回到错误提交后的状态。然后提交git revert。完成。

    不要删除现有的仓库! 只需在其他地方克隆新副本即可。如果出现问题,请保留现有的仓库。)

    更聪明的方法,这适用于几乎任何搞砸了回购的东西,就是使用git reflog找到最后一次已知的好提交并重置为该提交。 Git并没有重写历史,而是写下了新的历史,并说它总是发生的事情。所以你的旧提交仍然存在,有一段时间(比如几周)。

    当您运行git reflog时,您会看到以下内容:

    7efa9c7 (HEAD -> master) HEAD@{0}: commit: Testing 123
    f999b32 HEAD@{1}: commit: #fo
    7c6a630 HEAD@{2}: commit: # message with a comment
    1a0bddf HEAD@{3}: commit (initial): First commit
    

    HEAD一直在移动。 HEAD是当前签出的提交,因此提交,重置,签出,过滤分支,rebase ......这些都将移动HEAD。第一列是HEAD搬到的地方。第二种是引用该提交的符号方式。然后使用命令。最后是提交消息的第一行。

    你正在寻找类似的东西:

    deadbee HEAD@{?}: commit: The message of the wrong commit.
    123abcd HEAD@{?-1}: commit: This is the commit you want to move back to.
    

    然后git reset --hard 123abcd会在您犯错之前将您返回到提交。你之后做的所有其他事情都将被抹去。

    ... 除了 ,你做了一个影响 所有 分支的git filter-branch --all。所以你可能已经把你所有的分支都掏了。 git reset仅影响一个分支。

    同样,如果没有先了解Git的结构,请不要使用git filter-branchgit-resetgit-rebase之类的内容。它太糟糕了,但你可能会遇到很多麻烦。

    祝你好运!

答案 1 :(得分:0)

如果你的分支机构处于你希望它在本地的状态,你可以100%确定这一点,你可以

git push --force

将强制远程分支与本地分支完全相同。

警告:这将覆盖已推送到远程分支的所有更改。

您可以考虑使用其他一些方法来解决此问题。

  1. 拉出所有远程更改,然后撤消您反向执行的操作,然后将其作为新提交推送。
  2. git reset --soft HEAD^或在Windows git reset --soft HEAD~1中运行git push origin +branchName,这将取消移动文件的提交。