要移动已签出分支的分支指针,可以使用 git reset --hard
命令。但是如何移动未签出分支的分支指针以指向不同的提交(保留所有其他内容,如跟踪的远程分支)?
git branch <branch-name> <SHA-1-of-the-commit>
创建它的提交创建一个新分支并转储旧分支?
git branch --force <branch-name> [<new-tip-commit>]
如果省略 new-tip-commit
,则默认为当前提交。
new-tip-commit
可以是分支名称(例如,master、origin/master)。
您可以为任意参考做到这一点。这是移动分支指针的方法:
git update-ref -m "reset: Reset <branch> to <new commit>" refs/heads/<branch> <commit>
其中 -m
将消息添加到分支的 reflog。
一般形式是
git update-ref -m "reset: Reset <branch> to <new commit>" <ref> <commit>
如果您愿意,您可以挑选有关 reflog 消息的细节 - 我相信 branch -f
与 reset --hard
不同,这两者都不完全一样。
git branch -f
更好。具体来说,这种方法似乎是:(A)更难使用(B)更难记住,以及(C)更危险
您还可以传递 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
git update-ref
。
git reset --hard ...
这里不用重复了! :-(
只是为了丰富讨论,如果您想将 myBranch
分支移动到您的 current 提交,只需省略 -f
之后的第二个参数
例子:
git branch -f myBranch
我通常在 rebase
处于 Detached HEAD 状态时这样做:)
在 gitk --all
中:
右键单击您想要的提交
-> 创建新分支
输入现有分支的名称
在确认替换该名称的旧分支的对话框上按回车键。
请注意,重新创建而不是修改现有分支将丢失跟踪分支信息。 (对于只有一个遥控器并且您的本地分支与遥控器中的相应分支具有相同名称的简单用例,这通常不是问题。有关更多详细信息,请参阅评论,感谢@mbdevpl 指出这个缺点。)
如果 gitk
具有对话框具有 3 个选项的功能,那就太棒了:覆盖、修改现有或取消。
即使您通常像我一样是个命令行迷,git gui
和 gitk
也非常适合它们允许的 git 使用子集。我强烈建议将它们用于他们擅长的事情(即有选择地在 git gui 中将大块放入/退出索引,并且也只是提交。(ctrl-s 添加签名:行,ctrl-enter 提交.)
gitk
非常适合在您将更改整理成漂亮的补丁系列以提交上游时跟踪几个分支,或者在您需要跟踪多个分支中间的任何其他内容时跟踪。
我什至没有打开图形文件浏览器,但我喜欢 gitk/git gui。
git status
输出也会受到影响。此外,在某些情况下,如果您不设置跟踪分支,如果不明确指定远程,git fetch
和 git push
将无法工作。我不了解所有情况,但对我来说,一般的经验法则是,为了方便和工作速度,最好按顺序设置跟踪分支。
TortoiseGit 中的 recommended solution git branch -f branch-pointer-to-move new-pointer
:
“Git 显示日志”
检查“所有分支”
在您希望分支指针移动到的行上(new-pointer):右键单击,“在此版本创建分支”在“分支”旁边,输入要移动的分支的名称(branch-pointer-to-move)下“Base On”,检查新指针是否正确检查“Force”确定
右键单击“在此版本创建分支”
在“分支”旁边,输入要移动的分支的名称(branch-pointer-to-move)
在“Base On”下,检查新指针是否正确
勾选“强制”
好的
https://i.stack.imgur.com/jMZWU.png
https://i.stack.imgur.com/WZhnB.png
老实说,我很惊讶没有人想到 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
的不需要结帐的快速失败版本
Git 2.23.0 引入了 git-switch
命令,也可用于执行此操作。
git switch -C <branch-name> [<start-point>]
-C
(大写 C)选项表示如果 <branch-name>
已经存在,它将重置为 <start-point>
。
使用 -c
(小写 C)时,它将尝试创建一个新分支,但如果一个已经存在则失败。
<start-point>
可以是哈希、标签或其他分支名称。
git version 2.35.1
... git switch --help | egrep -i EXPERIMENTAL
说 THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
git switch
命令自 2.23.0 版中引入以来一直处于试验阶段。请参阅 2019 年 8 月的 Git 博客github.blog/2019-08-16-highlights-from-git-2-23
-c|-C
标志行为没有改变。
如果要将未签出的分支移动到另一个提交,最简单的方法是运行带有 -f 选项的 git branch 命令,该选项确定分支 HEAD 应指向的位置:
git branch -f <branch-name> (<sha1-commit-hash> or <branch-name>)
例如,如果您希望本地开发分支跟踪远程(源)开发分支:
git branch -f develop origin/develop
请注意,如果您尝试移动的分支是您当前的分支,这将不起作用。要移动分支指针,请运行以下命令: git update-ref -m "reset: Reset to " refs/heads/
git update-ref 命令安全地更新存储在 ref 中的对象名称。
希望我的回答对您有所帮助。信息来源是this snippet。
打开文件 .git/refs/heads/<your_branch_name>
,并将其中存储的散列更改为您要移动分支头部的散列。只需使用任何文本编辑器编辑并保存文件。只要确保要修改的分支不是当前活动的分支。
免责声明:可能不是一个可取的方法,但可以完成工作。
git commit
是使用 git 而不是 mercurial 的最令人信服的理由。
对于签出的分支,如果您要指向的提交在当前分支之前(除非您想撤消当前分支的最后一次提交,否则应该是这种情况),您可以简单地执行以下操作:
git merge --ff-only <commit>
这使得 git reset --hard
的替代方案更加柔和,如果您不是上述情况,则会失败。
要对未签出的分支执行相同的操作,等价于:
git push . <commit>:<branch>
git push . <commit>:<branch>
。
git merge --ff-only
,并且只有在没有冲突的情况下。
--ff-only
选项,但该选项不会改变合并的完成方式,它只会阻止非快进合并的完成。此外,如果合并不是快进,您可以拒绝提交并使用 git merge --abort
取消合并。
git merge
回答 OP 的问题需要更多的命令来保护起始分支和工作树。 git stash; git checkout <branch>; git merge --ff-only <commit>; git checkout <starting-branch>; git pop
不定期副业成功案例分享
git update-ref -m "reset: Reset <branch> to <new commit>" <branch> <commit>
。 (如果您愿意,您可以挑选有关 reflog 消息的细节 - 我相信branch -f
与reset --hard
不同,这两者都不完全一样。)git help branch
说“-f, --force 重置 <branchname> 到 <startpoint> 如果 <branchname> 已经存在。没有 -f git branch 拒绝更改现有分支。”git branch -f master <hash>
,它告诉我fatal: Cannot force update the current branch.
嗯,我现在必须做什么,在允许我使用此命令之前检查其他一些随机分支?HEAD
指向它),这将不起作用。