我再一次迷失在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
仅显示文件的最新更改。
思考?除了可能我应该放弃试图保留历史......:)
答案 0 :(得分:1)
我将一堆文件移动到项目中的新文件夹中。显然,这会丢弃移动文件的所有git历史记录。我之所以这么说,是因为当我做一个git log - 在任何移动的文件上它只显示最近的活动,而不是我在几个月内所做的所有事情。
Git没有跟踪重命名,git mv
是git rm
+ a git add
。相反,它根据文件的相似性进行猜测,这有其优点和缺点。
你经常需要给予一些鼓励。 git log
有多种选择可以做到这一点。 --follow
将遵循重命名后的单个文件的历史记录。 -C
也会检测副本。 -M
将跟随差异中的重命名。 git blame
有类似的选择。
但是当我回到Visual Studio时,我发现有一个传入的提取待处理。如果我进行任何其他本地更改并尝试提交它们,我会被告知由于挂起的传入提取而无法执行此操作。
我不知道Visual Studio正在做什么,而且我也不知道"等待传入的提取"是或为什么它会被阻止或阻止任何东西。 git fetch
始终是安全的。 它只会更新您的远程跟踪分支(即,它会更新您对远程仓库的看法)并且不会触及您的当地分公司。 git pull
是git 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的圆孔只会在不太长的时间内造成问题,因为我怀疑你现在正在经历
无论如何,对于你目前的情况,我认为发生了这件事。
那就是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-branch
或git-reset
或git-rebase
之类的内容。它太糟糕了,但你可能会遇到很多麻烦。
答案 1 :(得分:0)
如果你的分支机构处于你希望它在本地的状态,你可以100%确定这一点,你可以
git push --force
将强制远程分支与本地分支完全相同。
您可以考虑使用其他一些方法来解决此问题。
git reset --soft HEAD^
或在Windows git reset --soft HEAD~1
中运行git push origin +branchName
,这将取消移动文件的提交。