【问题标题】:How to "Un-push" a file in git?如何在 git 中“取消推送”文件?
【发布时间】:2021-12-23 07:14:13
【问题描述】:

您好,我是 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 的 GUI?
  • @AleksanderStelmaczonek 我正在使用命令行
  • 在这个场合,我总是推荐 git 书(第 1、2、3、7.1、7.2、7.3、7.7 章),这是一本很棒的书。 git-scm.com/book/en/v2
  • 是其他人在你的分支工作,还是只有你? (是否可以重写你的分支,甚至删除它,就好像你还没有推送它一样?)
  • @TTT 这个分支只有我一个人,你认为这是最好的解决方案之一吗?

标签: git version-control push git-commit


【解决方案1】:

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

话虽如此,在您的情况下,听起来您并不是真的想“取消推动”,而是“推动其他东西”(这也需要强制推动)。

如果您当前已签出 您的 分支,并且您位于刚刚提交的地方,并且 如果可以重写 您的 分支 因为没有其他人在使用它,那么这应该可以实现您想要的:

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. 再添加一个提交以删除您不想要的文件,然后将其推出。

【讨论】:

    【解决方案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"
    

    【讨论】:

      【解决方案3】:

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

      首先,恢复到提交之前

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-02-17
        • 2013-09-28
        • 1970-01-01
        • 1970-01-01
        • 2017-03-16
        • 1970-01-01
        • 2021-03-21
        相关资源
        最近更新 更多