无法使用git commit将提交添加到备用分支。有一些方法可以使用低级别的“管道”命令来完全按照您的描述进行操作,但是由这些命令形成的界面并不是为交互式使用而设计的1。当然有办法做你想做的事;根据您更改的详细信息和所涉及的分支的内容,它可能非常简单。
简单的案例:只需使用git checkout
切换分支时,git checkout将保留未提交的修改或拒绝切换(除非您使用--force
、--merge
或--conflict
)。因此,只要您未提交的更改仅触及 HEAD(当前分支)和目标分支中相同的文件,git checkout就会在切换分支时将这些更改留在索引和/或工作树中。如果您未提交的更改满足此条件,那么您可以这样做:
git checkout safe-branch
git add -- files-with-safe-changes
git commit
git checkout -
您还可以使用git add --patch
仅暂存和提交文件中的一些更改。
在此之后,您的“安全更改”将成为“安全分支”的一部分;切换回您的原始分支将“将它们抛在后面”(请记住,git checkout仅在切换分支时保留未提交的更改)。
如果您的其他更改依赖于“安全更改”,您可能需要将“安全分支”合并到您的工作分支中(或者,根据您的工作流程,将您的工作分支重新定位到“安全分支”的新提示上)。为此,您必须隐藏未提交的更改(因为如果有未提交的更改,合并和变基都将拒绝运行)。
git stash save
git merge safe-branch
git stash pop --index
如果您的其他更改不依赖于“安全更改”,那么您可能不应该为合并或变基而烦恼。最终,您会将这些分支合并在一起(例如,通过将它们合并到一个 'qa' 分支中以进行预发布测试),但没有理由过早地合并它们。
仍然很容易,但有点风险:git checkout -m
如果第一个git checkout抱怨“你有本地更改some‑file
;不切换分支。”,这意味着您有未提交的更改,some-file
并且该文件在“安全分支”的提示中与您当前的分支不同;您将需要一种不同的方法。
如果您确信更改将完全适用some‑file
于“安全分支”中的版本,那么您可以使用-m
/--merge
选项告诉git checkout尝试调整更改,以便它们适用于“安全”中的文件-分支'。如果合并不能干净地完成,那么您最终会遇到合并冲突,并且可能很难恢复您的原始更改(这就是我称之为“风险”的原因)。
安全:git stash
+git checkout -m
由于您真的只想将更改的子集移回“安全分支”,因此最好只关注这些更改。一种方法是使用git stash临时保存您当前的更改,这样您就不必将它们全部拖回“安全分支”(然后将其中的一些/大部分拖回您的工作分支)。
git stash save
git checkout stash -- files-with-save-changes
git checkout -m safe-branch
git commit
git checkout -
git stash pop --index
其他变化是可能的。您可以使用git checkout -p stash -- files
仅挑选出这些文件中的一些更改。如果索引中没有分阶段的更改,那么您可以首先分阶段“安全更改”,git add -- files
(同样,可选使用-p
),使用git stash save --keep-index
,切换分支(使用合并),然后提交(即git checkout stash -- files
用预先分阶段的“安全更改”替换变化”和git stash --keep-index
)。
在这种情况下,我认为git checkout -m
是安全的,因为我们使用git stash来保存当前更改的副本;如果三路合并尝试导致一团糟,那么您可以轻松放弃将“安全更改”放在“安全分支”上的想法并重新开始工作:切换回原始分支并弹出存储(git checkout -f - && git stash pop
)。
同样,如果您的其他更改依赖于“安全更改”,那么您将需要合并或变基。您也可以在弹出存储之前执行此操作(因为您需要一个干净的索引和工作树来执行合并/变基)。
如果您不打算立即将工作分支与“安全分支”合并(或将其重新设置为基础),那么您可能希望在弹出存储后撤消“安全更改”(“安全更改”是保存在原始存储中,您可能不希望在两个不同的分支中从头开始进行相同更改的提交2 )。弹出存储后,使用git checkout -- files-with-safe-changes
将这些文件恢复到工作分支顶端的版本。
1
“管道”界面专为在脚本中使用而设计。直接在命令行上使用它们会很麻烦。早期版本的git commit(和大多数其他 Git 命令)是基于此接口的 shell 脚本。它们今天仍然可以编写为 shell 脚本,但 C 版本通常要快得多。提交到备用分支所需的步骤是:
基于“安全分支”顶端的树设置备用索引,
使用“安全”更改更新索引(如果无法干净地应用更改怎么办?它很高兴有一个工作树来让用户解决冲突),
将索引写为树对象,
创建一个指向新树的新提交对象,并将“安全分支”的当前尖端作为其父级,
更新“安全分支”引用以指向新提交。
2
在两个分支中提交“安全更改”在技术上没有任何问题,但确保每个更改仅源自一个地方通常是个好主意。