将所有分支与 git 同步



我从两个主要位置推送代码:家里的电脑和工作的笔记本电脑。我使用 Github 来存储我的存储库。

场景是这样的:我在 PC 上做了一些工作,在我已经工作了一段时间的存储库上(在我的 PC 和笔记本电脑中),并以以下分支结束:

$ git branch
* master
* v123
* test-b

我推到了Github。目前为止,一切都好。

现在我在笔记本电脑上,这是我在尝试拉动任何东西之前看到的:

$ git branch
* master
* v_123

这是我笔记本电脑中存储库的旧版本(因为我一直在PC上工作),其区别在于:缺少一个分支(test-b),另一个分支已被重命名,或等效地删除并使用新名称重新创建(即:v_123现在v123),并且所有分支中都可能更改了很多内容。

我想将所有分支同步到我的笔记本电脑中并正确跟踪它们。我看了两个关于分支克隆/获取的最受好评的问题(如何在 Git 中克隆所有远程分支?如何获取所有 git 分支)现在我有点迷茫。

是否有一些易于使用的git sync-branch --all命令可用于将我的笔记本电脑与 Github 中存储库的最新状态同步?

我想你想:

git fetch --all -Pp

哪里: git fetch 从另一个(远程)存储库下载对象和引用

--all获取所有遥控器。

-P删除远程上不再存在的任何远程跟踪引用。

-p删除远程上不再存在的任何本地标记。

更多用途git fetch --help

我们有一个类似的命令,只执行修剪而不获取远程数据:

git remote prune origin

我们还可以将 git 客户端设置为每次获取数据时进行远程修剪:

git config --global fetch.prune true

不确定,这是您所期望的。

git fetch origin
git reset --hard origin/master
git clean -f -d

上述命令会将远程存储库与本地存储库同步。执行上述命令后,本地存储库将类似于远程存储库的镜像。

如果要将更改保留为非暂存文件,请使用 --soft 而不是 --hard

警告:当您执行git clean -f -d时,所有未跟踪的文件都将消失。

莱姆知道,如果有任何问题。

我遇到了类似的问题:

  • 我想一次同步所有本地跟踪分支
  • 我希望此操作是安全的。换句话说,在本地修改或分支发散的情况下,警告并且不要触摸历史记录(并且不要篡改未提交的修改)

在搜索了很多简单的解决方案之后,我最终得到了我自己的(不是那么简单)的解决方案,基于一系列 git 别名(要添加到.gitconfig文件中的代码): https://gist.github.com/arnauldvm/dcec7ee043c25dce30dbae1b576f2102

⚠ 这是新的代码,尚未经过如此严格的测试。

用法:git sync


一些解释:

tracking = "!f() { git for-each-ref --format '%(refname:short):%(upstream:short)' 'refs/heads' | egrep -v ':$'; }; f"

→ 这将检索所有本地跟踪分支和相应的远程分支,冒号分隔。

is-clean-workdir = "!f() { git diff --stat --exit-code || { echo "Workdir dirty"; exit 1; }; }; f"
is-clean-index = "!f() { git diff --stat --cached --exit-code || { echo "Index dirty"; exit 2; }; }; f"
is-clean = "!f() { git is-clean-workdir && git is-clean-index; }; f"

→ 这些将验证工作目录中没有挂起的更改。

co-merge = "!f() { local="$1"; remote="$2"; git checkout "$local"; git merge --ff-only "$remote"; }; f"

→ 这需要 2 个参数(本地分支和远程分支),它将签出本地分支并将其与远程分支合并。它使用--ff-only来避免创建提交合并⇒ 如果本地分支发散,它将在 STDERR 上发出"致命:无法快进,中止"消息。

current-branch = rev-parse --abbrev-ref HEAD

→ 检索当前签出的分支的名称。将用于在最后将工作目录恢复到其初始状态。

sync = "!f() { git is-clean || { echo Aborting sync.; exit 1; }; current=$(git current-branch); git fetch --all; git tracking | while IFS=: read local remote; do echo "Merging $local with $remote"; git co-merge "$local" "$remote"; done 3>&1 1>&2 2>&3 | egrep -i --color 'fatal|$' 3>&1 1>&2 2>&3; git checkout "$current"; }; f"

→ 这是主要部分。让我们将其分成几部分:

git is-clean || { echo Aborting sync.; exit 1; }

→→ 如果工作目录中有挂起的工作,则中止命令。

current=$(git current-branch)

→→ 存储当前签出的分支的名称。

git fetch --all

→→ 从所有远程同步远程分支 ( --all )。

git tracking | while IFS=: read local remote; do ...

→→ 循环访问每个本地跟踪分支。

3>&1 1>&2 2>&3 | egrep -i --color 'fatal|$' 3>&1 1>&2 2>&3

→→ 突出显示错误(包含"致命"关键字)。"3>&1 1>&2 2>&3"神奇的公式交换了STDOUT和STDERR,有必要能够通过管道将STDERR连接到egrep命令。

git checkout "$current"

→→ 将工作目录恢复到其初始状态。

在尝试拉取任何内容之前,您无法看到在远程上所做的任何更改。您必须先从远程获取。

这是有原因的。Git 是去中心化的。每个存储库都包含其完整副本。这意味着您可以从磁盘上的存储库创建完整克隆。这也意味着您可以完全离线工作,除非您命令它同步。实际上,git 的制作方式迫使你几乎完全离线工作,不包括你推送或获取的时刻。另一方面,您拥有完全控制权,没有明确说明,什么都不会发生。

怎么办?这就是git pull存在的原因。它执行两个操作。首先,它从远程获取所有分支(相当于 git fetch )。默认情况下,它们另存为<remote>/<branch>,不会列在分支列表中(用 -a 覆盖)。然后,它将当前活动的分支与其跟踪的分支合并。

现在,如果您想跟踪远程分支,则只需在拉动后将其签出即可。它将从上次同步的版本创建它,并应设置所有内容。如果要设置在远程上跟踪的非发布本地分支,请使用带有-u标志的git push。它将分支的上游设置为推送目标。

编辑:

因此,您的目标是使用一个命令一次更新所有本地跟踪的分支?不是那些<remote>/<branch>,而是你们当地的分支机构,没有对每一个分支都要求拉动,现在我说对了?

不幸的是,单独使用 git 是不可能的。但是有一个扩展可以做到这一点。来自项目描述

git-up - 获取并重定所有本地跟踪的远程分支

你可以在这里找到它 http://aanandprasad.com/git-up/

当您使用它时,使用命令 git up ,它将存储您当前的更改,获取所有远程,然后将所有跟踪的分支重新定位为来自跟踪的远程状态并取消存储更改。我相信这就是你想要的同步方式。

这是我编写的一个脚本,它将获取并快进所有分支,而无需执行任何签出(因此它更快并且不会影响您当前的工作树。

https://stackoverflow.com/a/24451300/965176

最新更新