简体   繁体   English

git checkout 分支不删除其中删除的文件

[英]git checkout branch without deleting the files deleted in it

Here is the situation I'm facing:这是我面临的情况:

A directory full of generated files where commited to the repo by mistake.一个充满生成文件的目录,错误地提交到 repo。 They obviously shouldn't have been, so I want to remove them:他们显然不应该,所以我想删除它们:

$ git rm --cached foo/*
$ cat > foo/.gitignore
*
!.gitignore
$ git add foo/
$ git commit -m "Ignored stuff in foo"

This almost solves it, but leaves a different problem.这几乎解决了它,但留下了一个不同的问题。 When I want to git fetch && git checkout on the production server, all the generated files in the foo/ directory will be removed.当我想在生产服务器上git fetch && git checkout时, foo/ 目录中所有生成的文件都会被删除。 Is there some magic I could do about it on either side?我可以在任何一方做一些魔术吗? Please not that simply ignoring them is not an option as they can be changed.请注意,简单地忽略它们不是一种选择,因为它们可以更改。

You can try a: 您可以尝试:

git fetch
git reset origin/master
git update-index --skip-worktree foo/*
git checkout --

The checkout should ignore the folder foo because of the git update-index command. 由于git update-index命令,因此检出忽略文件夹foo

Not sure this is the best way to do this, but I did it with this little hack: 不确定这是执行此操作的最佳方法,但我通过以下小技巧做到了:

The commit part is what I wrote in the question, the checkout is the tricky one: 提交部分是我在问题中写的,结帐是一个棘手的问题:

$ git fetch
$ git checkout origin/master && \
git log HEAD^..HEAD --summary --diff-filter=D \
| grep delete | awk '{print $4}' | xargs git checkout HEAD^ -- \
&& git reset HEAD

This way I checkout the latest commit in master, checkout everything that was deleted in the latest commit and then reset to HEAD so the deleted & checked-out file would be unstaged. 这样,我签出了master中的最新提交,签出了在最新提交中删除的所有内容,然后重置为HEAD,因此已删除和签出的文件将被取消登台。

It works, but I still would like to see some nicer way for this for the next time this happens. 它可以工作,但是我仍然希望在下次发生这种情况时,能找到更好的方法。

Introduction:介绍:

The accepted answer seems like it would work in some cases, but didn't seem like a perfect fit for what I was trying to do, so here's another approach:接受的答案似乎在某些情况下会起作用,但似乎并不适合我正在尝试做的事情,所以这是另一种方法:

Backstory:背景故事:

I'm trying to keep track of what files some software generates, and so I'm committing various things into a git repo that I don't ever intend to share, just to see what's there.我正在尝试跟踪某些软件生成的文件,因此我将各种内容提交到 git 存储库中,我不打算共享这些内容,只是为了看看那里有什么。

Some files are created that are labeled as temp.创建了一些标记为临时文件的文件。 I want to capture them in git, but mostly, I want to ignore them, and not track changes regularly (but be able to, if I want to), so, I wanted to create a branch with-temp-files , check the files in there, but then not get rid of the files when switching back to my main branch, where I'd then add a .gitignore to ignore them while I'm on main.我想在 git 中捕获它们,但大多数情况下,我想忽略它们,而不是定期跟踪更改(但如果我愿意,可以),所以,我想创建一个with-temp-files的分支,检查那里的文件,但是当切换回我的main分支时不会删除这些文件,然后我会在主分支上添加一个.gitignore以忽略它们。

The problem with the accepted answer (for me):已接受答案的问题(对我而言):

When doing the git reset , I was just going resetting to main -- there is no origin (or any other remote), so that didn't make sense.在执行git reset时,我只是要重置到main - 没有origin (或任何其他遥控器),所以这没有意义。 And I'm wanting to keep a branch that has the files, I just don't want them on my main branch.我想保留一个有文件的分支,我只是不想让它们在我的主分支上。

My solution, for my situation:我的解决方案,针对我的情况:

  1. Starting from a worktree that's got these new files in it, but is otherwise pristine从一个包含这些新文件的工作树开始,但在其他方面是原始的
  2. git add temp -- add the extra files git add temp -- 添加额外的文件
  3. git commit -- get them into the repo git commit它们放入 repo
  4. git branch with-temp-files -- now create a new branch on the commit that has the files added, but don't switch to it . git branch with-temp-files - 现在在添加了文件的提交上创建一个新分支,但不要切换到它
  5. git reset HEAD^ -- reset main to back before the new commit, leaving with-temp-files as its own branch. git reset HEAD^ -- 在新提交之前将 main 重置为 back,将with-temp-files保留为其自己的分支。 The working tree is left alone (the files are still there, now again in an untracked state).工作树保持独立(文件仍然存在,现在再次处于未跟踪状态)。

A potentially more generalize-able answer:一个可能更通用的答案:

  1. Assuming you have a tree that has these added files, but no other changes since adding them (if this is not your situation, then more care is needed; beyond the scope of this answer)假设您有一棵树,其中包含这些添加的文件,但添加后没有其他更改(如果这不是您的情况,则需要更加小心;超出此答案的 scope)
  2. Determine the commit that contains the unwanted files, let's pretend it's abc123确定包含不需要的文件的提交,假设它是abc123
  3. Determine the commit that's prior to the unwanted files having been added, let's pretend it's def456 (though it could be indirectly referenced with something like origin/main ).确定添加不需要的文件之前的提交,让我们假装它是def456 (尽管它可以用origin/main之类的东西间接引用)。
  4. [optional, if you want to keep track of the branch] use either git branch with-files abc123 or git tag with-files abc123 (changing with-files to any name you desire) [可选,如果你想跟踪分支]使用git branch with-files abc123git tag with-files abc123 (将with-files更改为你想要的任何名称)
  5. Run git reset def456 to go back to a state before the files were added.在添加文件之前运行git reset def456 to go 回到 state。 Without other arguments (eg --hard , which would remove things -- not what we want here) , the reset should leave the new files in the worktree.如果没有其他 arguments (例如--hard ,它会删除一些东西——这不是我们在这里想要的) ,重置应该将新文件留在工作树中。

Hopefully this adds some additional insights for anyone else trying to work through similar situations.希望这能为其他试图解决类似情况的人增加一些额外的见解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM