git - 提交到未 checkout 的分支

标签 git

我正在使用git在几台不同的计算机上对主目录进行版本控制。我希望他们每个人都使用单独的分支,并且都从同一个分支中提取。因此,除非正在提交特定于该计算机的特定内容,否则大多数提交都应提交给该公共(public)分支,在这种情况下,提交应转到已 check out 的特定于计算机的分支。在这种情况下,切换分支显然不是一个很好的选择。

this post中提到我想做的事是不可能的,但是我发现答案很直率,也许没有考虑使用管道命令的可能性。不幸的是,我没有足够的声誉来对该线程发表评论。我宁愿怀疑有某种方法可以做到这一点,并希望只问您一个好人就可以节省一个小时或很少的时间来寻求答案。

那么有可能在不首先检查该分支的情况下提交到另一个分支吗?理想情况下,我想以与git commit通常相同的方式使用索引。

最佳答案

我相信,执行所需操作的最佳方法是在特定于计算机的分支上进行提交,然后使用git rebase移动它们。这大约是我对自己的主目录所做的操作-与您的主目录基本相同。

# make a new branch starting from branch machine_1
git checkout -b move_to_master      
# make whatever commits you need to
git rebase --onto master machine_1 move_to_master
git checkout master
git merge move_to_master  # this is a fast-forward
git checkout machine_1
git merge master

如果您在创建move_to_master之前意外地提交到machine_1,只需创建move_to_master,然后将machine_1重置回它所属的位置,然后执行其余步骤即可。

但是,您的问题值得回答,我在底部提供了更多其他选择。

创建不在当前分支上的提交

注意事项:非常非常小心!这是可怕的东西!

可以提交到没有使用管道命令 check out 的分支,这只是非常必要的。您必须使索引进入所需的状态(这可能很棘手),然后可以使用git commit-tree:
git commit-tree -p $PARENT_COMMIT < $COMMIT_MESSAGE_FILE

这将打印以输出新创建的提交对象的SHA1。假设PARENT_COMMIT是分支技巧,则必须使用git update-ref将分支更新为它:
git update-ref -m "commit: [commit subject]" $BRANCH $NEW_SHA1

如果要编写脚本,则可以单行作为git update-ref -m ... $(git commit tree ...)来实现。这是最恐怖的一步。如果您将其他分支更新-ref到错误的位置,则很糟。您仍然可以通过git reflog show $BRANCH找出将其重置回何处的方法。

无论如何,这只是简单的部分。真正困难的事情是使索引进入所需状态,而无需实际 check out 文件。您可能会使用的两个常用命令:
  • git read-tree-将树信息读入索引,但根本不更新工作树(git checkout大致等效于git read-tree,git checkout-index和git update-ref HEAD)。您可以使用它来使索引包含该未 checkout 分支的内容,而不是HEAD。
  • git update-index-修改索引。您可以使用它在工作树中添加,删除或刷新索引中的文件。
  • git checkout-index-将索引中的给定路径复制到工作树中。使用读取树后,您可以使用它来获取要更改的单个文件,对其进行修改,然后将其放回带有update-index的文件中。 “修改”步骤可能很复杂-例如,在执行所有操作之前,您可以使用git diff创建一个补丁,然后在此处使用git apply进行应用。
  • git apply --cached使用--cached选项,此选项将补丁直接应用于索引中的版本,而无需触及工作树。因此,您可以创建一个diff,在另一个分支上读取树,将其应用于索引,提交树,然后进行设置。这可能是最棒的方法。

  • 之所以如此困难,是因为所有允许您访问其强大 merge 功能的git命令都依赖于文件在工作树中。考虑一下时,您要执行的任务是 merge -您在一个分支上有一个差异,并想在另一个分支上应用它。获得结果的方法是使用原始分支上的diff,与另一个分支的公共(public)祖先以及另一个分支的尖端进行三向 merge 。如果没有其他分支 checkout ,您将无法真正完成 merge !

    像往常一样使用管道命令执行操作时,您应该非常小心地了解一切如何工作,以免严重破坏存储库。就是说,在重组现有存储库(由其他人创建的存储库……不要问)的时候,我实际上已经使用了这一功能。在这种情况下,我只是重新排列提交-使用读取树而不是通常使用update-index-因此它比您可能尝试的要简单得多。

    替代方法

    综上所述,您还可以采用其他两种方法来完成所需的操作。
  • 克隆您的存储库。如果您只跟踪配置文件,则不会占用太多空间,事情会容易得多。如果您真的很着迷,甚至可以使用git new-workdir(链接到git.git HEAD中的版本)脚本仅创建一个工作目录,而不复制其余的repo(它使用.git目录中的符号链接(symbolic link)) 。只是要记住要小心地将一个工作目录提交到在另一个工作目录中 checkout 的分支,而另一个工作目录最终将导致其工作树不同步。
  • 编写一个单提交包装脚本-这是对所有这些选项的另一个分支进行单提交的最接近的方法:
    git commit
    orig_branch=$(git symbolic-ref HEAD)
    orig_branch=${orig_branch#refs/heads/}
    git checkout master
    git cherry-pick $orig_branch
    git checkout $orig_branch
    git reset --hard HEAD^
    
  • 关于git - 提交到未 checkout 的分支,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2481338/

    相关文章:

    git - 有谁知道用于 windows 的 git bash 程序用于其 shell 的是什么?

    ios - 要从 ios 项目的 git 存储库中排除哪些文件?

    将一组提交限制在特定分支的 git 策略

    git - 使用 go 从源代码安装 git-lfs - 找不到包

    git - 使用 Git 存储库时遇到问题

    git - 如何仅保留 Git 存储库的最新版本

    node.js - NPM - Fork 模块,更改代码并将 PR 发送给作者

    git - 如何使 git 跟踪文件/文件夹名称大小写更改?

    linux - git 可以用来处理 repo 中的项目吗?

    git - 为什么将 git 存储库复制到另一个目录后我修改了文件?