将分支指针移至其他提交而无需检出


759

要移动已检出分支的分支指针,可以使用以下git reset --hard命令。但是,如何移动未检出分支的分支指针以指向不同的提交(保留所有其他内容,如跟踪的远程分支)?


11
听起来您想要做的只是从一个不同于现在创建的提交的分支。如果我的理解是正确的,那为什么不简单地使用要创建的提交git branch <branch-name> <SHA-1-of-the-commit>并通过转储旧分支来简单地创建一个新分支呢?
yasouser 2011年

6
@yasouser-我不确定转储“ master”分支是一个好主意。
Bulwersator

Answers:


578

您可以为任意引用执行此操作。这是移动分支指针的方法:

git update-ref -m "reset: Reset <branch> to <new commit>" refs/heads/<branch> <commit>

一般形式:

git update-ref -m "reset: Reset <branch> to <new commit>" <ref> <commit>

如果愿意,您可以选择关于reflog消息的内容-我相信branch -f一个与另一个不相同reset --hard,但这不完全是其中之一。


39
信息对哪里有好处?它存储在哪里以及以后如何读取?
2012年

4
注意:这不适用于裸存储库。在裸仓库上,您必须使用'git branch -f master <commit>'更新分支(请参见下面的答案)。
6

37
如果像我一样,不小心使用了<branch>而不是refs / heads / <branch>,则会在.git目录中的.git / <branch>中得到一个新文件,并且会收到类似尝试使用它时,“ refname'master'是不明确的”。您可以从.git目录中删除该文件以进行修复。
David Minor

34
至今还没有令人满意的解释为什么这比更好git branch -f。具体来说,这种方法似乎是:(A)难以使用(B)难以记住,并且(C)更加危险
Steven Lu

10
“任意引用确切地意味着什么”-分支不是指向提交的唯一引用。有标签,您也可以自己创建既不是分支也不是标签的任意ref / whatevs / myref样式ref。我相信,这也回答了鲁迅关于这可能是“更好”的问题。我同意如果您正在使用分支,则branch -f最简单。
亚当

962
git branch -f <branch-name> <new-tip-commit>

24
或对于任意参考,git update-ref -m "reset: Reset <branch> to <new commit>" <branch> <commit>。(如果愿意,您可以选择关于reflog消息的内容-我相信branch -f一个与另一个不相同reset --hard,而且这两个都不完全相同。)
Cascabel 2011年

4
Jefromi,请另外写一个答案,以便获得投票。:)
蒙特

16
这是一个更好的答案,因为它可以处理99%的案例并实际上符合文档要求。git help branch说:“ -f,--force如果<branchname>已经存在,将<branchname>重置为<startpoint>。不使用-f git branch拒绝更改现有分支。”
AlexChaffee

12
我在做git branch -f master <hash>,这是在告诉我,fatal: Cannot force update the current branch.我现在必须做些什么,在允许使用此命令之前检查其他随机分支?
Qwertie 2014年

20
如果您要移动的分支是当前分支(HEAD指向该分支),则此方法将无效。
弗拉基米尔·潘捷列耶夫(Fladimir Panteleev)

135

您还可以传递git reset --hard提交参考。

例如:

git checkout branch-name
git reset --hard new-tip-commit

我发现我经常做这样的事情:

假设这个历史

$ git log --decorate --oneline --graph
* 3daed46 (HEAD, master) New thing I shouldn't have committed to master
* a0d9687 This is the commit that I actually want to be master

# Backup my latest commit to a wip branch
$ git branch wip_doing_stuff

# Ditch that commit on this branch
$ git reset --hard HEAD^

# Now my changes are in a new branch
$ git log --decorate --oneline --graph
* 3daed46 (wip_doing_stuff) New thing I shouldn't have committed to master
* a0d9687 (HEAD, master) This is the commit that I actually want to be master

这是最有意义的,因为通常使用HEAD或HEAD ^来使分支提示及时返回。因此,这与指定前面的提交是一致的。
justingordon 2014年

11
如果您的工作树是干净的,那很好。如果您有很多分阶段或非分阶段的更改,则最好git update-ref按照上面的讨论进行。
2014年

16
您是否注意到您的“答案”没有添加任何已经不属于问题的内容?– OP说:如果已签出...您可以使用git reset --hard ...无需在此处重复!:-(
罗伯·西默2015年

6
@罗伯特:我不同意。问题没有说明如何使用它,而是这样做。很高兴不必去寻找那种方式。
Wilson F

7
@WilsonF,也许很高兴在这里找到这个,但它根本没有回答问题。也许这是其他一些问题的答案,但这是错误的
罗伯特·西默

52

只是为了丰富讨论,如果您想将myBranch分支移至当前提交,只需在第二个参数之后省略-f

例:

git branch -f myBranch


当我rebase处于HEAD分离状态时,通常会这样做:)


13

gitk --all

  • 右键单击所需的提交
  • -> 创建新分支
  • 输入现有分支的名称
  • 在对话框中按Return键,确认替换该名称的旧分支

请注意,重新创建而不是修改现有分支将丢失跟踪分支信息。(对于简单的用例,通常情况下这不是问题,因为只有一个遥控器,并且您的本地分支与该遥控器中的相应分支具有相同的名称。有关更多详细信息,请参见注释,感谢@mbdevpl指出了这一缺点。)

如果gitk对话框具有3个选项,那就很酷了:覆盖,修改现有的或取消。


即使你是一个正常的命令行迷像我一样,git guigitk被很好地设计为使用的git的子集,它们允许。我强烈建议您将它们用于自己的特长(例如,将大块选择性地转移到git gui中的索引中/从索引中转移出来,并且也只是提交。(ctrl -s来添加签名:: )

gitk 当您将更改整理到一个不错的修补程序系列中以提交到上游时,或者在需要跟踪多个分支中间的任何其他内容时,它非常适合跟踪几个分支。

我什至没有打开图形文件浏览器,但是我喜欢gitk / git gui。


1
太简单!我可能刚刚从gitg转换为gitk。
Michael Cole

但是,这种方式会丢失跟踪分支信息。
mbdevpl

@mbdevpl:我不是真正的git专家。我想我理解您的意思,但不明白含义。我经常使用它,但仍然能够将这些分支推送到远程上同名的分支。分支机构及其远程跟踪分支机构之间的关联对您有什么作用?
彼得·科德斯


1
@PeterCordes Ineed,当分支名称不匹配时很重要。同样,当有多个遥控器时。同样,当您使用git提示显示分支状态时,它将显示到跟踪分支的提交距离(如果已设置)。此外,git status输出也会受到影响。此外,在某些情况下git fetchgit push如果您未设置跟踪分支,则必须在没有显式指定远程的情况下使用。我并不了解所有情况,但对我而言,一般的经验法则是,为了方便和快捷地工作,最好按顺序跟踪分支。
mbdevpl


4

老实说,我很惊讶没有人想到该git push命令:

git push -f . <destination>:<branch>

点(。)表示本地存储库,您可能需要-f选项,因为目标可能位于“远程副本的后面”

尽管此命令用于将更改保存到服务器中,但其结果与将远程分支(<branch>)移动到与本地分支(<destination>)相同的提交时完全相同


您也可以这样做,而不会-f避免破坏本地内容。举例来说,git fetch origin && git push . origin/develop:develop是一个没有结帐需要快速失败的版本git checkout develop && git pull --ff-only
btown

1

打开文件.git/refs/heads/<your_branch_name>,然后将存储在其中的哈希值更改为要移动分支头的哈希值。只需使用任何文本编辑器编辑并保存文件即可。只要确保要修改的分支不是当前活动的分支即可。

免责声明:可能不是建议的方法,但是可以完成工作。


1
不确定这是混沌还是邪恶的方法。🤔😉
基思·罗素

@KeithRussell可能都是:P
GuillermoGutiérrez

0

如果您要指向的提交在当前分支之前(除非您要撤消当前分支的最后一次提交,否则应该是这种情况),只需执行以下操作:

git merge <commit>

询问是否未签出分支该怎么办。
基思·罗素

糟糕,我错过了这一点。在这种情况下,您可以git push . <commit>:<branch>按照建议进行操作。
让·保罗
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.