Git 拉力覆盖本地文件

Git Pull Force to overwrite local files

"Git Pull Force", "git reset branch to origin" 或者换句话说,拉出远程分支覆盖本地分支,似乎是一个被广泛搜索的功能,尽管本地下降很少,但人们越来越感兴趣。

对于不断壮大的团队和越来越多的开发人员来说,这绝对有意义。

目前,最短的工作解决方案非常冗长,需要分支知识

git reset --hard origin/<branch_name>

edit: There is a more convenient variant git reset --hard @{u}.
Please give credit where it is due . More shortcuts here.

不幸的是,输入以下内容要快得多

git pull

然而,这也带来了自身的挑战。不同的历史,合并冲突等...


我们确实有这样的速记

git push origin HEAD -u --force

将本地分支 <branch_name> 推送到原点,覆盖具有相同名称的远程分支 <branch_name> 并将其设置为自己的上游分支。

但是,没有 --force/reset 替代 git pull


将此功能添加到 git 的最佳方法是什么?


How do I force "git pull" to overwrite local files? 660 万次浏览
Reset local repository branch to be just like remote repository HEAD 470 万次浏览
How do I force git pull to overwrite everything on every pull? 37 万次观看
Resolve conflicts using remote changes when pulling from Git remote 24 万次观看
How to force update when doing git pull? 9 万次观看
Force GIT Pull without commiting
Force a pull with git
git force pull with implicit rebase
Clean up a fork and restart it from the upstream


您至少需要三个命令:

  • 一次获取,更新远程跟踪分支
  • a重置到上游分支,使用
  • 清理以确保没有留下额外的文件

即:

git fetch
git reset --hard @{u}
git clean -nd

(将 git clean 中的 -nd 选项替换为 -fd 以实际删除文件:我总是更喜欢 首次预览 git clean 就可以了,在实际删除任何东西之前)

您必须将它们分组为别名或脚本 (git-pullreset),然后您可以调用它们。


LeGEC suggests in :

git stash
git restore -SW -s @{u} -- .
git reset @{u}

That would:

  • leave completely untracked files (e.g: files not tracked in HEAD nor in @{u}) untouched, and
  • would give a way to still have something to revert to "how it was before".

我要强调的是,虽然您肯定提到了每天都会出现的需求,但 git 在没有警告的情况下强行 删除您的工作 的命令也是问题的来源,造成更严重的后果(寻找“我在 git reset --hard / git checkout . 之后丢失了我的工作,我可以找回它吗?”问题)。

以你的 pull -f 为例,当你使用遥控器 inetract 时,你不知道你会得到什么 来自遥控器。

根据我的拙见,我强烈建议养成不使用git pull的习惯,只使用git fetch

然后检查与origin/branchname的差异,然后选择是否要重置或变基或...


最好有一个命令说“移动到该提交并放弃所有更改”,我将在这里重复我在对 的评论中建议的内容:

#!/bin/bash

target=
if [ -z "$target" ]; then
    target=HEAD
fi

set -e  # avoid going forward if one command fails ...

git stash
git restore -SW -s "$target" -- .
git reset "$target"

(我没有好的别名:git goto?)

它是 git reset 的一个相当安全的替代方案;主要警告是:磁盘上的文件,在开始提交时未跟踪但在 $target 中跟踪,将被覆盖而不保存。

您还需要更复杂的 git stash 变体来保存这些文件。


[更新] 我想我找到了一个脚本,它设法隐藏了受影响的文件(而且只有那些):

#!/bin/bash

target=
if [ -z "$target" ]; then
    target=HEAD
fi

set -e  # avoid going forward if one command fails ...

list_impacted_files () {
   local target=

   # tracked files in the working tree that have a diff
   git diff --no-renames --name-only HEAD

   # untracked files that will be clobbered when restoring $target :
   #   * files that are present in $target but not in HEAD
   #   * and that currently exist on disk (use 'ls' to keep only those)
   # add '|| true' to ignore error code returned by 'ls' on non existing files
   git diff --no-renames --name-only --diff-filter=A HEAD "$target" |\
     xargs -r ls 2> /dev/null || true 
}

# list files as described above, and feed this list to `git stash -u`
# 'xargs -r <cmd>' avoids running <cmd> at all if stdin is empty
# in our case: don't run 'git stash -u' if no files are to be stashed ...
list_impacted_files "$target" | xargs -r git stash -u --

git restore -SW -s "$target" -- .
git reset "$target"

要将您的存储库恢复到原来的样子:

  • 恢复到初始提交(使用 git reset 或上面的脚本...)
  • git stash list
  • 中找到要恢复的 stash@{xx}
  • 运行 git stash apply --index stash@{xx}

我将采取不同的方法,挑战问题的前提。如果您发现自己必须调整本地分支以匹配远程分支,这表明 您不应该以 开头的本地分支。

相反,您使用的分支 远程跟踪分支,因此无需调整。

就拿我来说吧。我整天都在灵活地制作小功能分支并推动它们形成拉取请求以合并到主分支。但是我自己没有main。我需要它做什么?没有!

  • 为了启动功能分支,我获取并创建了从 origin/main 开始的分支。
  • 为了研究远程 main 的状态,我获取然后查看 origin/main,分离。
  • 为了审查拉取请求,我获取并签出 origin/yourbranch,分离。

所以我唯一拥有的本地分支是我自己的功能分支 — 它们 没有上游 并且不能被拉动(而且不需要,因为唯一他们的进一步承诺将来自我)。

简而言之,我建议如果人们真的想知道如何将“拉出远程分支来覆盖本地分支”作为他们常规工作流程的一部分,这仅仅表明他们正在使用 Git 一开始就错了。除非:

,否则永远不要创建本地分支机构
  • 您将向其添加提交并推送它,或者
  • 您将在本地合并到其中,这在当今的拉取请求世界中通常不是这种情况,或者
  • 它纯粹是本地的和实验性的,即您只是在开发功能时尝试一种可能的方法。

None 这些场景将 曾经 涉及相应的远程跟踪分支,因此问题中提出的情况永远不会出现。