我有一个本地开发服务器,我会对其进行所有更改,我们将其称为local
。
我在webserver
的git文件夹中设置了git repo,我们称之为gitfolder
。
然后我有我的实时文件,每当我推送时都会从gitfolder推送,我们称之为live
。
我的工作流程。
编辑文件,提交更改,推送到webserver
。然后更新后接管以下内容:
#!/bin/sh
export GIT_WORK_TREE=/path/to/live
git checkout -f
这完美无缺。但是,这就是我的问题。我想恢复git更改,我通常会通过git reset --hard commit
执行此操作 - 但如果我导航到live
,那么显然这不是git repo。
当我转到gitfolder
并运行相同的命令git reset --hard commit
时,它不会更新live
并且我得到错误'致命:此操作必须在工作树中运行“
采取的步骤?现在,我已经离开并复制了我的local
文件夹并创建了local2
- 并在local2
上我还原了更改,然后将其推送到live
,所以我原来的local
文件夹仍然包含所有更改。
我不想改回local
- 只需live
答案 0 :(得分:3)
你可能不想改变服务器中的任何引用(git reset
会移动任何分支HEAD
点,可能是master
,但你说你不&# 39;我想恢复或重置您的本地系统,所以基于此,我假设您不想恢复或重置您的裸存储库。)
在这种情况下,只需登录服务器cd
到裸存储库,然后运行:
git checkout --work-tree=/path/to/live checkout -f <commit-ID>
或:
GIT_WORK_TREE=/path/to/live git checkout -f <commit-ID>
换句话说,您只是执行更新挂钩所执行的操作,但使用原始提交ID来提取该特定版本,而不更改存储库本身中的任何分支。
虽然我认为这是您问题的字面答案,但我想指出一些其他内容:如果您git revert
在您自己的本地存储库中进行了错误的提交,那么您会得到一个新的提交撤消错误提交的效果,但错误的提交仍在那里。然后,您可以按照通常的方式将结果推送到服务器:
... - o - X - o - U <-- master, origin/master
其中X
是错误的提交,而U
是&#34; un-does&#34; X
做了什么。仅仅是为了说明,我在他们之间也包含了一个无趣的o
提交。
现在您可以简单地还原您的还原,以便您的本地回购结束于&#34;坏&#34;提交再次重播:
... - o - X - o - U <-- origin/master
\
X' <-- master
其中X'
是错误提交的副本,其中&#34;取消&#34; U
所做的撤消。您现在可以修复它,在顶部或git commit --amend
等处进行另一次提交,当它完成后,再次git push
将结果发送到服务器。这将是解决问题的更典型方式。
根据评论,这是另一个选项,可能适合也可能不适合,更好等:不是在本地重置或恢复,而是创建一个新的本地分支或标记(让我们在这里使用分支)要在服务器上恢复的提交。您可能还需要服务器上的名称,以便它不会进行垃圾收集提交(这意味着您将不得不在以后再次通过网络发送它们)。
例如,让我们说local
上的树看起来像这样,用扭结绘制,以便我可以添加标签:
... - o - R
\
X - o - o -...- o <-- HEAD=master, origin/master
此处R
是您希望服务器重置的提交,而X
和其他提交是更新Wordpress插件等的提交。 (我假设您正在分支master
上工作;根据需要进行更改。)
同时,在服务器上,事情看起来像这样:
... - o - R
\
X - o - o -...- o <-- HEAD=master
如果要保留服务器上的所有提交,我们应该为最终o
提交一个新的分支名称,因为我们必须强制更新master
。所以在local
上,我们可以运行:
$ git push origin master:save
这将在服务器上创建一个名为save
的新分支,现在看起来像这样:
... - o - R
\
X - o - o -...- o <-- HEAD=master, save
update
挂钩将执行通常的git checkout -f
,它会检出HEAD
分支(因为没有指定分支),在本例中为master
,所以服务器更新到最后o
提交(毫无意义,它已经存在)。但接下来,我们再次在local
上执行此操作:
$ git branch for-server <commit-ID-for-R>
这会将local
上的设置更改为如下所示:
... - o - R <-- for-server
\
X - o - o -...- o <-- HEAD=master, origin/master
还不是很有趣,但接下来:
$ git push --force origin for-server:master
这个(带有--force
)告诉服务器强行更新其master
以指向提交R
,之后它有:
... - o - R <-- HEAD=master
\
X - o - o -...- o <-- save
save
标签将剩余的提交保留在服务器上的存储库中。同时,post-update
挂钩运行并执行git checkout -f
,其使用HEAD
,其指向master
,其指向提交R
。因此,Web服务器现在应该已部署提交R
。
回到local
,您只需要记住for-server
映射到遥控器上的master
。 (如果您愿意,可以重命名所有本地分支以匹配服务器上的命名:例如,将master
更改为save
,然后将for-server
更改为master
。 #39; s全部独立于此。)
请注意,save
唯一在服务器上执行的操作是保留提交X
和所有后续o
。如果您想直接在服务器上工作,或者不想通过网络发送这些提交,那就太好了。但是,如果在服务器(具有工作目录,因为它不是一个简单的回购),git checkout save
,您将HEAD
更改为指向{{ 1}}并且下次save
挂钩运行时,它将部署post-update
版本,而不是save
版本。