Git从两次提交前回滚

Git从两次提交前回滚,git,Git,几天前,我从master分支,并向newbranch提交了两份后续承诺 后来,我注意到我所做的第一次提交中的一个文件不应该被更改。我还没有将任何内容推送到主分支,我所有的更改都在newbranch中。如何将newbranch中的这一个文件回滚到我最初从master分支时的位置?git checkout master--filepathgit checkout master--filepath在新分支上: git checkout HEAD~1 git checkout HEAD~1 file_n

几天前,我从master分支,并向
newbranch
提交了两份后续承诺


后来,我注意到我所做的第一次提交中的一个文件不应该被更改。我还没有将任何内容推送到主分支,我所有的更改都在
newbranch
中。如何将
newbranch
中的这一个文件回滚到我最初从master分支时的位置?

git checkout master--filepath
git checkout master--filepath
在新分支上:

git checkout HEAD~1
git checkout HEAD~1 file_not_needed
git commit -a --amend
git cherry-pick new_branch
git branch -f new_branch HEAD
关于新科:

git checkout HEAD~1
git checkout HEAD~1 file_not_needed
git commit -a --amend
git cherry-pick new_branch
git branch -f new_branch HEAD

根据您想要的结果,有几种不同的方法来实现这一点

这个

开始时,您的提交历史记录如下所示(每个字母代表一次提交):

(这种签出形式,
git checkout
,告诉git更改
头的名称。在本例中,
头1
,意思是“查找提交头的名称并向后移动一个”,所以这表示从commit
E
向后移动一个。由于这是一个特定的
,而不是一个分支名称,因此它还具有“分离头”效果。)

现在运行
git checkout HEAD~1 filename
。为了对git更加明确,可以说
git checkout HEAD~1--filename
-->
表示“剩余参数是文件名,而不是分支或修订名”-如果省略
-->
,git会尝试猜测它是分支名还是文件名

这种形式的
签出
,带有
--filename
参数,做了一些完全不同的事情:它说要像往常一样查找修订版
头~1
,但这次,不要更改
,只提取给定的文件。由于
HEAD
现在命名了修订版
D
,git又备份了一个修订版
C
,并从该修订版中提取文件
filename
的版本,并将其放入工作目录

(请注意,分支名称
master
也命名为revision
C
,因此此时您可以编写
git checkout master--filename
。)

接下来,
git commit-a--amend
告诉git添加任何更改的文件。在这种情况下,您实际上不需要它,但一般来说,这会添加您已修复的其他文件,然后执行“amend commit”。“修改提交”意味着“创建一个新提交,但使其父提交与我们的父提交相同”。这将创建一个新的提交,我们将其称为
D'
,其父级为
C
。与往常一样,新提交将成为
标题
。由于
HEAD
已分离,因此尚未移动分支名称。生成的提交树如下所示:

A - B - C               <-- master
        | \
        \   D
          \   \
            \   E       <-- newbranch
              \
                D'      <-- HEAD
现在,您只需要给
指定一个分支名称。然后可以安全地删除
newbranch
,或者将其重命名,然后将
newnewnew
重命名为
newbranch

git checkout -b newnew          # now HEAD=newnew which points to E'
git branch -m newbranch oldnew  # rename out of the way
git branch -m newnew newbranch  # and rename newnew to newbranch
(你可以把它缩短一点,但让我们继续…)


有一种更简单的方法来做同样的事情。只需运行
git-rebase-i master
。这意味着使用
master
作为当前分支的“上游”来重新设置当前分支(
newbranch
)的基础。也就是说,找到
master
(这意味着
D
E
)之后的所有提交,并将它们重新设置到
master
(这是它们以前的基础)。如果没有
-i
这将是愚蠢的,将
D
E
重新设置为与以前完全相同的方式,这只是一种昂贵的方式,除了使用
-i
git可以打开一个编辑器来执行一系列命令。这些命令将
pick
提交
D
E
。将提交
D
选择
更改为
编辑
,然后写出文件

然后,rebase将为您选择
D
,并停止,让您修改提交。在shell中,输入:

git checkout master -- filename
git commit -a --amend
与前面一样,保存修改后的提交,它将变成
D'
。然后运行:

git rebase --continue
Git现在将选择commit
E
,并给出commit
E'
。现在一切都完成了,这样重基就完成了,branch
newbranch
有了您想要的提交


这家公司做了一些不同的事情。它包含相同的
git签出主机--filename
(拼写为
filepath
),但没有类似于rebase的序列

因此,与之前一样,您从以下内容开始:

A - B - C             <-- master
          \
            D
              \
                E     <-- HEAD=newbranch

A-B-C根据您想要的结果,有几种不同的方法可以做到这一点

这个

开始时,您的提交历史记录如下所示(每个字母代表一次提交):

(这种签出形式,
git checkout
,告诉git更改
头的名称。在本例中,
头1
,意思是“查找提交头的名称并向后移动一个”,所以这表示从commit
E
向后移动一个。由于这是一个特定的
,而不是一个分支名称,因此它还具有“分离头”效果。)

现在运行
git checkout HEAD~1 filename
。为了对git更加明确,可以说
git checkout HEAD~1--filename
-->
表示“剩余参数是文件名,而不是分支或修订名”-如果省略
-->
,git会尝试猜测它是分支名还是文件名

这种形式的
签出
,带有
--filename
参数,做了一些完全不同的事情:它说要像往常一样查找修订版
头~1
,但这次,不要更改
,只提取给定的文件。由于
HEAD
现在命名了修订版
D
,git又备份了一个修订版
C
,并从该修订版中提取文件
filename
的版本,并将其放入工作目录

(请注意,分支机构名称
master
也命名为修订版
C
git rebase --continue
A - B - C             <-- master
          \
            D
              \
                E     <-- HEAD=newbranch