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

时间:2011-10-28 18:00:32

标签: git version-control branch git-branch

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

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

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

11 个答案:

答案 0 :(得分:17)

这是不可能的。

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

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

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

pages工作副本中,将master副本添加为远程回购。

  • 您在master
  • 上提交了网页
  • master副本
  • 上的pages拉出
  • 推送到GitHub
  • 将master分支重置为先前的状态。

答案 1 :(得分:12)

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

这可以通过对git hash-object

的各种调用来完成

但这很难实现。

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

答案 2 :(得分:10)

只要您当前的索引中没有任何与您希望保留的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}

我们实际上从未检查过otherbranch,我们的工作树文件尚未被触及。

答案 3 :(得分:9)

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

但是,从Git 2.5开始(2.6中有一些重要的修复,从那时起有一些重要的修复),使用git worktree add执行此操作的实用方法。

例如,让我们说您希望同时处理分支maindoc""或分支developtest"在同一时间",但有问题的两个分支故意包含不同的东西。 (例如,doc分支具有存在于代码外部或旁边的文档,或者test分支具有将针对代码运行但未分发或预期会出现故障的测试故意在develop方面或其他方面跳过哪些测试。)

而不仅仅是:

git clone -b develop <source> theclone

然后在theclone工作,并在两个分支之间来回不断切换,你会:

git clone -b develop <source> theclone

然后:

cd theclone
git worktree add ../ct test  # check out branch test in ../ct

或只是:

git worktree add ../test     # check out branch test in ../test

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

答案 4 :(得分:3)

虽然目前没有单一命令可以执行此操作,但至少有两个其他选项。

  1. 您可以使用github api创建提交。 This post详细说明了在github仓库中创建提交。

  2. Create github pages as a submodule

  3. 使用一系列管道命令来创建提交 用于创建提交的管道命令的git book has a description

  4. 注意:该命令现在是mktree而不是mk-tree

答案 5 :(得分:3)

我不能同意这是不可能的。通过混合git stash pushgit stash popgit checkoutgit checkoutgit addgit commit,这是可能的。

我如何理解问题:

您在分支主机上,并对文件patched.txt进行了一些修改,并且您希望将此文件提交给其他分支。

您想要做的是:

  • 通过执行git stash
  • 保存此仓库中的所有更改
  • 从stashed stack结帐file.txt
  • 将文件patched(仅此文件)添加到新分支
  • 在modyfing file.txt
  • 之前回到repo状态

这可以通过执行以下命令来实现:

destBranch=patch
thisBranch=master
FileToPutToOtherBranch="file1.txt file2.txt 'file with space in name.txt'"
message="patched files $FileToPutToOtherBranch"
                                                                                  #assumption: we are on master to which modifications to file.txt should not belong
git stash &&\                                                                     #at this point we have clean repository to $thisBranch
git checkout -b $destBranch &&\           
git checkout stash@{0} -- $FileToPutToOtherBranch &&                              #if there are many files, repeat this step                                         #create branch if does not exist (param -b)
git add $FileToPutToOtherBranch &&\                                               # at this point this is equal to git add . --update
git commit -m "$message" &&\
git checkout $thisBranch &&\
git stash apply &&\                                                               # or pop if want to loose backup
git checkout $thisBranch -- $FileToPutToOtherBranch                               # get unpatched files from previous branch

我之所以使用&#34;&amp;&amp;&#34;最后是如果有人将这个片段复制并粘贴到终端,即使发生一个错误,也会执行下一个命令,这是不好的。 \用于通知shell命令在下一行继续。

为了证明这一点,我为这个片段提供了测试环境

mkdir -p /tmp/gitcommitToAnyBranch && cd /tmp/gitcommitToAnyBranch &&\
git init 
echo 'this is master file' > file1.txt
echo 'this is file we do not want to have modified in patch branch because it does not     patches any feature' > docs.txt
git add file1.txt && git commit -m "initial commit" 
echo 'now this file gets patched' > file1.txt
git status

现在,如果您使用参数

运行我的脚本
destBranch=patch
thisBranch=`git rev-parse --abbrev-ref HEAD`
FileToPutToOtherBranch="file1.txt"
message="patched file $FileToPutToOtherBranch"

您只会在补丁分支中修改file1.txt,有关详情,请参阅gitk --all

答案 6 :(得分:2)

我制作了一个完全符合这个要求的小工具:https://github.com/qwertzguy/git-quick

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

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

答案 7 :(得分:2)

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

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

o--o--o (main)
    \
     o (foo)

我想在签出 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

那我们做了什么?本质上,我们完成了普通添加提交例程所做的所有步骤,并做了一些调整。

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

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

情况如下:

        o (new commit)
       / 
o--o--o (main)
    \
     o (foo)

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

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

完成!

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

最后,一举完成所有事情的单线:

git branch -f main $(git commit-tree $(git write-tree) -p main -m "commit message")

write-tree 的散列输出立即用作 commit-tree 的输入,其输出立即用于移动分支。

答案 8 :(得分:1)

如果您意外修改了错误分支中的内容,请执行以下简单步骤:

  1. 提交这些更改;
  2. 将它们合并到正确的分支中;
  3. 首先检查您所在的分支,然后将其重置为之前的提交;
  4. 使用&#34; git checkout - 。&#34;。
  5. 清理您的修改

    此后一切都应该没问题。您还可以选择性地合并,重置和清理修改。

答案 9 :(得分:0)

我就是这样做的:

如果我已经意外提交,请回滚一次提交:

git reset --soft 'HEAD^'

添加您要添加​​的文件

git add .

创建一个新的临时分支:

git checkout -b oops-temp

提交您的更改:

git commit -m "message about this commit"

结帐您要查看的分行:

git checkout realbranch

合并旧分支:

git merge oops-temp

删除旧分支:

git branch -D oops-temp

答案 10 :(得分:0)

不,您不能,但是import pandasdmx as sdmx df = sdmx.Request('OECD').data( resource_id='MEI_FIN', key='IR3TIB.GBR+USA.M', params={'startTime': '2008-06', 'dimensionAtObservation': 'TimeDimension'}, ).write() 使用提交来实现硬拷贝文件的操作。 git stash作为更改的堆栈工作,这些更改被保存在“分支空间之外的某个地方” ,因此可用于在分支之间移动修改。

  • stash上进行更改
  • git add <file>
  • git stash
  • git checkout <file>
  • git stash pop
  • git commit -m“ <branch you want to commit>

如果您经常这样做,则可以将这些简单的命令放下来。