12 git
假设我有一个版本号为A的存储库.我想将其更新到版本B,而最新版本是C.(版本A早于B,B早于C).我是git的新手,所以我做了一些研究,发现了这个,这激发了我一个解决方案:
git pull # update from A to the latest revision C
git reset --hard B
Run Code Online (Sandbox Code Playgroud)
这确实有效.但是由于我不能git reset --hard B直接从A更新到最新的先例更新仍然太重,我不知道可能有一些单行命令来满足我的需要.有什么提示吗?
Séb*_*ans 20
没有"将存储库更新为某个版本".您的存储库具有所有版本,这就是git fetch/ git pull做什么.
如果您想在本地工作树中放置一个特定的repo版本,有几种方法可以做到这一点.最接近您的问题是:
更新本地存储库:
git fetch origin
Run Code Online (Sandbox Code Playgroud)
创建一个新的分支(从你当前所在的任何分支,我们稍后将重置,所以它无关紧要):
git branch yourbranchname
git checkout yourbranchname
Run Code Online (Sandbox Code Playgroud)
上述两个操作可以缩写为一个(当前HEAD被假定为分支的源):
git checkout -b yourbranchname
Run Code Online (Sandbox Code Playgroud)
然后将该分支的指针放在您需要的提交(B):
git reset --hard sha1-of-B
Run Code Online (Sandbox Code Playgroud)
git reset --hard将始终有效,它不依赖于你的分支的历史,它工作的唯一条件是提交B在你的本地对象库中(即B必须存在并且必须从远程仓库获取这不是你的工作).
正如@Hasturkun指出的那样,你也可以使用额外的参数直接从任意哈希分支:
git checkout -b yourbranchname SHA-1
Run Code Online (Sandbox Code Playgroud)
你的做法是完全错误的。您正在修改您不想修改的内容:您当前的分支(大概是master)。
一个简单的线性 git 存储库是一个像这样的提交链
*---A---*---*---B---*---*---C
^ ^
| |
master origin/master
^
|
HEAD
Run Code Online (Sandbox Code Playgroud)
这是您调用后存储库的状态git fetch。请注意,整个历史及其所有中间步骤都在您的本地硬盘上。只是您只A检查了提交时的状态(HEAD指向master哪个指向A),因此您看到的文件属于该状态。
现在,如果您只想查看作为 提交的状态B,您可以使用git checkout B. 这会将您看到的文件更新为B,并指向HEAD该提交:
*---A---*---*---B---*---*---C
^ ^ ^
| | |
master HEAD origin/master
Run Code Online (Sandbox Code Playgroud)
HEAD始终引用git认为您所在的提交/分支,并且在您调用git status.
git checkout B如果您只想查看该提交,那么简单就足够了。如果您确实想要进行您提交并想要保留的更改,您应该引入一个新分支来记录这些更改。这是通过一个简单git checkout -b newBranch的git checkout B. 这会给你状态
*---A---*---*---B---*---*---C
^ ^ ^
| | |
master newBranch origin/master
^
|
HEAD
Run Code Online (Sandbox Code Playgroud)
这只是给出了一个提交的名称,B而不是它的哈希值。再进行一些提交后,您的状态将如下所示:
*---A---*---*---B---*---*---C
^ | ^
| | |
master \ origin/master
\
*---*---D
^
|
newBranch
^
|
HEAD
Run Code Online (Sandbox Code Playgroud)
关键是,在使用 检出其他分支/提交后git checkout ...,您始终可以D通过调用轻松返回到提交git checkout newBranch,并且永久引用停止git垃圾收集提交D。
现在,为什么使用git reset --hard不好?首先,它会破坏您尚未提交的所有本地更改,恕不另行通知。其次,如果您不小心,它可能会丢失您的历史记录。
例如,考虑这样一种情况,您在上次推送到上游存储库后进行了一些更改,并希望查看一些历史提交B。(与您问题中的情况有些相反。)历史看起来像这样:
*---A---*---*---B---*---*---C
^ ^
| |
origin/master master
^
|
HEAD
Run Code Online (Sandbox Code Playgroud)
使用git reset --hard B,您将获得以下状态:
*---A---*---*---B-(-*---*---C )
^ ^
| |
origin/master master
^
|
HEAD
Run Code Online (Sandbox Code Playgroud)
括号中的提交不再被任何分支直接或间接引用,并且可能随时被垃圾收集。git垃圾收集可能不是很激进,但是如果它在您处于这种状态时进行垃圾收集,则您无法C恢复提交,它将永远丢失。您不希望这种情况发生,因此养成git reset --hard轻率使用的习惯并不是一个好主意。
如果您git checkout改用,分支master仍将指向C,并且您仍然可以使用简单的git checkout master.