如何 "Un-push" git 中的文件?

How to "Un-push" a file in git?

你好,我是 Git 的新手。我在我的分支上工作,我不小心提交并推送了一个我修改过的文件(但不希望出现在我的拉取请求中)。例如:我推了 fileA.pyfileB.pyfileC.py。但是我只想要 fileA.pyfileB.py 在拉取请求中。

来自

- FileA.py
- FileB.py
- FileC.py

- FileA.py
- FileB.py

我找到的大部分答案都涉及删除 fileC.py。我不想实际删除 fileC.py,我仍然希望它在 repo 中只是像 master 中那样的未修改版本。有没有 git 命令来实现这个?感谢您的帮助!

在 Git 中,“取消推送”相当于 强制 推送您推送之前的内容。您是否应该 force 推送取决于几个因素,主要因素是其他人是否可能正在构建您已经推送的分支版本。通常在 public 回购中强制推送是不受欢迎的,而在私人回购中它在 共享分支 上不受欢迎(例如 mainmasterdevelop, 等等)

也就是说,在你的情况下,听起来你并不是真的想“取消推动”,而是“推动其他东西”(这也需要用力推动)。

如果您当前您的 分支已签出,并且您在刚刚提交的位置,并且如果可以重新提交-write your branch 因为没有其他人在使用它,那么这应该实现你想要的:

git reset --mixed @~1 # Go back to the previous commit; leave files alone
git add FileA.py FileB.py # Stage only the files you want to commit.
git commit -m "Add files for new thing"
git push --force-with-lease # Using --force-with-lease is usually best practice

第一行中的注释 --mixed 是多余的,因为默认重置是混合的。该行可以改为 git reset @~1。我把它留在里面,所以从学习的角度来看它更清楚,因为你是 Git.

的新手

备选方案: 如果条件不允许(或不应该)强制推送您的分支,那么您可以:

  1. 通过还原之前的提交来创建新的提交,然后重新创建新的正确提交,并将这 2 个提交推出。
  2. 再提交一次删除您不想要的文件,然后将其推出。

警告:既然你提到了拉取请求,我假设你正在推送到一个单独的分支,除了你之外没有其他人在处理。否则,通常不鼓励用力推动。


让我们假设一些状态:

$ touch fileA.py fileB.py fileC.py
$ git add .
$ git commit -m "my message"
$ git push
$ ls
fileA.py*  fileB.py*  fileC.py*  
$ git ll
* 537443d - (HEAD -> my-branch) my message (9 seconds ago) <Aleksander Stelmaczonek>
  0     0       fileA.py
  0     0       fileB.py
  0     0       fileC.py  

注意:git ll是我自定义的命令别名,定义见文末


要从提交中删除 fileC.py 并将其保留在工作目录中,您可以使用 git rm 命令然后修改您的提交并重新推送它(强制推送)替换原来的提交一个修改后的。请注意,默认情况下,此命令还会从磁盘中删除文件,您需要使用 --cached 选项。

$ git rm -h
usage: git rm [<options>] [--] <file>...

    -n, --dry-run         dry run
    -q, --quiet           do not list removed files
    --cached              only remove from the index
    -f, --force           override the up-to-date check
    -r                    allow recursive removal
    --ignore-unmatch      exit with a zero status even if nothing matched

现在:

$ git rm --cached fileC.py
rm 'fileC.py'

$ git status
On branch my-branch
Changes to be committed:
        deleted:    fileC.py

Untracked files:
        fileC.py

$ git commit --amend -m "my message"
[my-branch beebdc1] my message
 Author: Aleksander Stelmaczonek <Olek@TPOLEK.localdomain>
 Date: Wed Nov 10 18:25:37 2021 +0100
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 fileA.py
 create mode 100644 fileB.py

$ git ll
941acb2 - (HEAD -> my-branch) my message (13 seconds ago) <Aleksander Stelmaczonek>
  0     0       fileA.py
  0     0       fileB.py

$ ls
fileA.py*  fileB.py*  fileC.py*

$ git push --force

我想强烈强调如果有多个人在做,那么强制推送是一个非常糟糕的主意这个分支。潜在问题不是那么容易解决的,尤其是对于新手。

总的来说,我强烈推荐阅读Git Book。它是免费的,而且写得很好。对于新手,值得一读的是第1、2、3、7.1、7.2、7.3、7.7章


就个人而言,对于与创建和修改提交相关的所有内容,我通常只使用 GUI。找出最适合您的 GUI 工具。我使用 https://git-fork.com/.


这就是您如何使用我的 git ll 命令 (and others) 增强您的 git 体验:

git config --global alias.ll "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %Cblue<%an>%Creset' --abbrev-commit --date=relative --numstat"

听起来您想替换推送的提交。 (不建议在多用户设置中像这样重写历史记录。)

首先,恢复到提交之前

git reset HEAD^

然后重新创建提交并推送新提交。您将需要使用武力。

git push --force-with-lease   # A safer version of -f/--force

开始之前,您应该标记问题提交。

git tag bad

这使您可以在出现任何问题时轻松恢复原始状态。

git checkout mybranch   # In case you changed away
git reset --hard bad