git 将文件提交到不同的分支而无需签出

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7933044/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 06:07:15  来源:igfitidea点击:

Commit a file to a Different Branch Without Checkout

gitversion-controlbranchgit-branch

提问by Schneems

Is it possible to commit a file in a git branch with out checking out that branch? If so how?

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

Essentially I want to be able to save a file in my github pages branch without switching branches all the time. Any thoughts?

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

Update:It's not possible to do what I want (see comments below for use case). What I ended up doing is programmatically cloning my current directory to a tmp directory, then checking out my branch in that tmp directory (doesn't affect my working directory) and committing my files to the tmp directory clone. When I'm done, I push back to my working directory and delete the tmp directory. Sucks, but it's the only way to commit files to another branch without changing the current working branch of the working directory. If anyone has a better solution, please feel free to add it below. If it's better than 'it cannot be done', I'll accept yours.

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

采纳答案by CharlesB

It's not possible.

这是不可能的。

The changes you commit are related to the current working copy. If you want to commit to another branch it means that you could commit changes from your working copy, but base them from another copy state.

您提交的更改与当前工作副本相关。如果你想提交到另一个分支,这意味着你可以从你的工作副本提交更改,但是它们基于另一个副本状态。

This is not a natural way of versioning your work, and this is why you need to make different steps (stash changes, checkout the branch, pop stash and commit) to accomplish it.

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

As for your specific use case, a simple way is to keep two copies of your work, one checked out at masterbranch, and the other at pagesbranch.

至于您的特定用例,一个简单的方法是保留您的工作的两份副本,一份在master分支检出,另一个在pages分支。

In the pagesworking copy, add the mastercopy as a remote repo.

pages工作副本中,将副本添加master为远程存储库。

  • You commit pages on master
  • Pull from masteron the pagescopy
  • push to GitHub
  • reset the master branch at its previous state.
  • 你提交页面 master
  • 从副本master上拉pages
  • 推送到 GitHub
  • 将 master 分支重置为其先前的状态。

回答by p'tit fred

It can be done by reimplementing git commit.

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

This can be done with various call to git hash-object

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

But this is hard to achieve.

但这很难实现。

Please read progit chapter 9for more details and a full example of how to simulate a commit.

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

回答by CB Bailey

So long as you don't have anything in your current index that differs from your HEADthat you want to keep you can so something like this. (If you do want to keep your index you could temporarily export the GIT_INDEX_FILEenvironment variable to point at a temporary file for the duration of these commands.)

只要您当前的索引中没有与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}

We've never actually checked out otherbranchand our working tree files haven't been touched.

我们从来没有真正签出过otherbranch,我们的工作树文件也没有被触及。

回答by torek

As several others have said, it is literally possible, but impractical.

正如其他几个人所说,这确实是可能的,但不切实际。

However, as of Git 2.5 (with some important fixes in 2.6 and minor ones since then), there isa practical method for doing this using git worktree add.

但是,从 Git 2.5 开始(在 2.6 中进行了一些重要的修复,然后次要修复),有 一种实用的方法可以使用git worktree add.

Let's say, for instance, that you want to work on branches mainand doc"at the same time", or branches developand test"at the same time", but the two branches in question deliberately contain different things. (For instance, the docbranch has documentation that exists outside or alongside the code, or the testbranch has tests that will be run against the code, but not distributed, or which are expected to have failures for which tests are deliberately skipped on the developside, or whatever.)

比方说,比如,要在分支机构的工作main,并doc“在同一时间”,或分支机构developtest“在同一时间”,但问题的两个分支故意含有不同的东西。(例如,doc分支具有存在于代码外部或旁边的文档,或者test分支具有将针对代码运行但未分发的测试,或者预期会出现故障而故意跳过测试的测试develop,管他呢。)

Instead of just:

而不仅仅是:

git clone -b develop <source> theclone

followed by working in theclonewith constant switching back and forth between the two branches, you would:

然后theclone在两个分支之间不断来回切换,您将:

git clone -b develop <source> theclone

but then:

但是之后:

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

or just:

要不就:

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

Now you can run your tests in ../testwhile developing in theclone. You can merge and/or rebase changes from one branch to the other in the usual way: the underlying repository is already shared, so no git pushor git fetchis required. You simply have bothbranches checked out, into two separate work-trees, named thecloneand testfrom the top level.

现在,您可以../testtheclone. 您可以以通常的方式将更改从一个分支合并和/或重新设置为另一个分支:底层存储库已经共享,因此不需要git pushgit fetch不需要。您只需将两个分支都检出到两个独立的工作树中,命名theclonetest从顶层开始。

回答by test30

I cannot agree it is not possible. By mixing git stash push, git stash pop, git checkout, git checkout, git addand git committhis is possible.

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

How I understand problem:

我如何理解问题:

You are on branch master and you made some modifications to file patched.txtand you would like to commit this file to other branch.

您在 master 分支上并且对文件进行了一些修改,patched.txt并且您想将此文件提交到其他分支。

What you would like to do is:

你想做的是:

  • save all changes in this repo by doing git stash
  • checkout file.txtfrom stashed stack
  • add file patched(and only this file) to new branch
  • get back to state of repo before modyfing file.txt
  • 通过执行 git stash 保存此 repo 中的所有更改
  • file.txt从隐藏的堆栈中结帐
  • 将文件patched(仅此文件)添加到新分支
  • 在修改之前回到回购状态 file.txt

This can be achieved by executing following commands:

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

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

The reason why I am using "&&" and the end is if somebody will copy&paste this snippet into terminal, even if one error occurs, next commands will be executed, which is not good. \ is for informing shell that command is continued in next line.

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

To proove this works I provide testing environment for this snippet

为了证明这是有效的,我为此片段提供了测试环境

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

Now, if you run my script with parameters

现在,如果您使用参数运行我的脚本

destBranch=patch
thisBranch=`git rev-parse --abbrev-ref HEAD`
FileToPutToOtherBranch="file1.txt"
message="patched file $FileToPutToOtherBranch"

You will have file1.txtmodified only in patch branch, for more see gitk --all

您将file1.txt仅在补丁分支中进行修改,有关更多信息,请参见gitk --all

回答by qwertzguy

I made a little tool that does exactly this: https://github.com/qwertzguy/git-quick

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

It let's you edit specific files from another branch without checking out the other branch completely (just the files you want to edit) and commit them. All this without ever affecting your working copy or staging area.

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

Behind the scenes it uses a combination of git worktree and sparse checkout. The source is fairly small, so you can read through.

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

回答by codingFoo

While there is currently no single command to do this, there are at least two other options.

虽然目前没有单一的命令可以做到这一点,但至少还有其他两个选项。

  1. You could use the github api to create the commit. This postdetails creating a commit in a github repo.

  2. Create github pages as a submodule.

  3. Use a series of plumbing commands to create the commit.
    The git book has a descriptionof plumbing commands used to create a commit

  1. 您可以使用 github api 创建提交。 这篇文章详细介绍了在 github 存储库中创建提交。

  2. 创建 github 页面作为子模块

  3. 使用一系列管道命令来创建提交。
    git book描述了用于创建提交的管道命令

note: the command is now mktree not mk-tree

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

回答by Arteymix

If you accidently modified things in the wrong branch, here's some simple steps :

如果您不小心修改了错误分支中的内容,这里有一些简单的步骤:

  1. Commit these changes ;
  2. Merge them into the right branch ;
  3. Checkout the branch your were on at first and reset it to the commit before ;
  4. Cleanup your modifications with "git checkout -- .".
  1. 提交这些更改;
  2. 将它们合并到正确的分支中;
  3. 首先检查您所在的分支并将其重置为之前的提交;
  4. 用“git checkout -- .”清理你的修改。

Everything should be fine after this. You can also merge, reset and cleanup your modifications selectively.

在这之后一切都应该没问题。您还可以有选择地合并、重置和清理您的修改。

回答by leandro souza rosa

No you cannot, however what you are doing by hard copying files is implemented by git stashusing commits. The stashworks as a stack of changes that are saved "somewhere outside the branches spaces", hence can be used to move modifications between branches.

不,你不能,但是你通过硬拷贝文件所做的事情是通过git stash使用提交来实现的。该stash作品作为保存在“分支空间之外的某处”的一堆更改,因此可用于在分支之间移动修改。

  • Make your changes on <file>
  • git add <file>
  • git stash
  • git checkout <branch you want to commit>
  • git stash pop
  • git commit -m "<commit message>"
  • 进行更改 <file>
  • 添加 <file>
  • 混帐
  • 结帐 <branch you want to commit>
  • git stash pop
  • git commit -m " <commit message>"

you can probably scrip these simple commands down if you do this constantly.

如果你经常这样做,你可能可以把这些简单的命令写下来。

回答by jordan314

This is how I do it:

这就是我的做法:

if I've acidentally committed, roll back one commit:

如果我已经认真地提交了,请回滚一次提交:

git reset --soft 'HEAD^'

add the files you want to add

添加要添加的文件

git add .

create a new temporary branch:

创建一个新的临时分支:

git checkout -b oops-temp

commit your changes:

提交您的更改:

git commit -m "message about this commit"

checkout the branch you meant to check out:

结帐您打算结帐的分支:

git checkout realbranch

merge the old branch:

合并旧分支:

git merge oops-temp

delete the old branch:

删除旧分支:

git branch -D oops-temp