在没有Checkout的情况下将文件提交到不同的分支

Sch*_*ems 30 git version-control branch git-branch

是否可以在git分支中提交文件而不检查该分支?如果是这样的话?

基本上我希望能够在我的github pages分支中保存文件,而无需一直切换分支.有什么想法吗?

更新:不可能做我想做的事情(请参阅下面的用例说明).我最终做的是以编程方式将当前目录克隆到tmp目录,然后在该tmp目录中检出我的分支(不影响我的工作目录)并将我的文件提交到tmp目录clone.当我完成后,我会回到我的工作目录并删除tmp目录.很糟糕,但这是将文件提交到另一个分支而不更改工作目录的当前工作分支的唯一方法.如果有人有更好的解决方案,请随时在下面添加.如果它比'不能做'更好,我会接受你的.

Cha*_*esB 18

这是不可能的.

您提交的更改与当前工作副本有关.如果要提交到另一个分支,则意味着您可以从工作副本提交更改,但是可以从另一个副本状态进行更改.

这不是对您的工作进行版本控制的自然方式,这就是为什么您需要执行不同的步骤(存储更改,检出分支,弹出存储和提交)来完成它.

至于您的具体用例,一种简单的方法是保留两份工作副本,一份在master分支机构检出,另一份在分支机构检出pages.

pages工作副本中,将副本添加master为远程仓库.

  • 你提交页面 master
  • 从副本master上拉出来pages
  • 推送到GitHub
  • 将master分支重置为先前的状态.

  • http://pages.github.com/这是一种直接使用github提供文档或演示页面等html内容的方法.它必须在一个单独的分支中,因为这就是github写它的方式.虽然数据(在这种情况下是文档)与项目有关,但由于多种原因,它不应该在主分支中,因为压缩了master的提交消息,其中包含与代码无关的更改. (2认同)
  • 这个答案如何正确?您提交的更改与您的工作副本无关。它们完全基于添加到索引中的内容。你可以删除工作树中的所有内容,并且仍然“git commit”,就好像什么也没发生一样,因为 git 只查看索引。 (2认同)

小智 12

它可以通过重新实现git commit来完成.

这可以通过各种调用来完成 git hash-object

但这很难实现.

请阅读progit第9章以获取更多详细信息以及如何模拟提交的完整示例.


CB *_*ley 11

只要你当前的索引中没有任何东西与HEAD你想要保留的东西不同,你就可以这样.(如果您确实要保留索引,则可以GIT_INDEX_FILE在这些命令的持续时间内临时导出环境变量以指向临时文件.)

# Reset index and HEAD to otherbranch
git reset otherbranch

# make commit for otherbranch
git add file-to-commit
git commit "edited file"

# force recreate otherbranch to here
git branch -f otherbranch

# Go back to where we were before
# (two commits ago, the reset and the commit)
git reset HEAD@{2}
Run Code Online (Sandbox Code Playgroud)

我们从来没有实际检查过otherbranch,我们的工作树文件没有被触及.


tor*_*rek 10

正如其他几位人士所说,这实际上是可能的,但不切实际.

然而,正如吉特2.5(含2.6一些重要的修复,从那时起次要的),还有 就是做这个用的实用方法git worktree add.

例如,假设您想要在分支机构上工作main,doc"同时",或分支机构developtest"同时",但有问题的两个分支有意包含不同的内容.(例如,doc分支具有存在于代码外部或旁边的文档,或者test分支具有将针对代码运行但未分发的测试,或者预期会出现故障的测试被故意跳过的测试develop,管他呢.)

而不仅仅是:

git clone -b develop <source> theclone
Run Code Online (Sandbox Code Playgroud)

然后继续在theclone两个分支之间来回切换,你会:

git clone -b develop <source> theclone
Run Code Online (Sandbox Code Playgroud)

但是之后:

cd theclone
git worktree add ../ct test  # check out branch test in ../ct
Run Code Online (Sandbox Code Playgroud)

要不就:

git worktree add ../test     # check out branch test in ../test
Run Code Online (Sandbox Code Playgroud)

现在,您可以在../test开发过程中运行测试theclone.您可以通常的方式将更改从一个分支合并和/或重新绑定到另一个分支:底层存储库已经共享,因此不需要git pushgit fetch不需要.您只需两个分支签出,分成两个单独的工作树,命名theclonetest从顶层.


Pet*_*ter 9

这里的大多数答案都说这是不可能的,或者使用隐藏。它可以在不隐藏的情况下完成,但这并不容易,而且我认为这不是你想要纳入日常生活的事情。

对于这个例子,我从一个主分支和一个 foo 分支开始。

o--o--o (main)
    \
     o (foo)
Run Code Online (Sandbox Code Playgroud)

我想在签出 foo 时将文件提交到 main 。我这里写的命令都是在没有检查main的情况下完成的。

git add examplefile
git write-tree  
    # this returns a hash: 2ceb75e10358ba27aaf2291e4e302d759fbedd55
git commit-tree 2ceb75e10358ba27aaf2291e4e302d759fbedd55 -p main -m "commit message"  
    # this makes a commit with commit the main branch points to as parent
    # it too returns a hash: 56823299cdc8b6c1ab30095f6b2c2143f3bb2122
git branch -f main 56823299cdc8b6c1ab30095f6b2c2143f3bb2122
    # this points the main branch to the new commit
Run Code Online (Sandbox Code Playgroud)

那么我们做了什么?本质上,我们执行了正常添加提交例程执行的所有步骤,并进行了一些调整。

首先,我们像平常一样将文件添加到暂存区。接下来,我们运行git write-tree. 它将暂存区域写入一棵树并返回该树的哈希值。提交只不过是一个指向树的指针、一个指向其父级的指针和一条消息。

然后,我们实际上通过给它所需的三样东西来进行提交:树、父级(主)和提交消息。请注意,在我的计算机上,此命令不会打开提交消息的编辑器,因此我需要在命令行中给出它。您的体验可能会有所不同。

那么情况如下:

        o (new commit)
       / 
o--o--o (main)
    \
     o (foo)
Run Code Online (Sandbox Code Playgroud)

我们在正确的位置进行了新的提交。然而,它是悬空的,这意味着没有分支(或标签)指向它。我们现在必须将 main 指向新的提交。

最后一个命令正是这样做的。它获取新创建的提交的哈希值并将 main 指向它。

完毕!

正如我在开始时所说的:这不是你想要经常做的事情。正常的添加提交策略是经过深思熟虑的。这个策略可能会搞乱一些你不知道的事情。它不检查冲突,它只是覆盖文件而不提及它。

最后,一句台词可以一举完成所有事情:

git branch -f main $(git commit-tree $(git write-tree) -p main -m "commit message")
Run Code Online (Sandbox Code Playgroud)

write-tree 的哈希输出立即用作 commit-tree 的输入,并且其输出立即用于移动分支。


qwe*_*guy 5

我制作了一个小工具,可以做到这一点: https: //github.com/qwertzguy/git-quick

它允许您编辑另一个分支中的特定文件,而无需完全签出另一个分支(只是您要编辑的文件)并提交它们。所有这一切都不会影响您的工作副本或暂存区域。

它在幕后结合使用 git worktree 和稀疏结帐。来源相当小,所以你可以阅读。