简体   繁体   English

Git:如何更新master分支,一步切换到master分支?

[英]Git: How to update the master branch and switch to it in one step?

I'm working on a project that's hosted on GitLab and uses issue/work branches and merge requests to bring that work into the master branch when it's done.我正在处理一个托管在 GitLab 上的项目,并使用问题/工作分支和合并请求在完成后将该工作带入主分支。 Usually I work on issue branches.通常我在问题分支上工作。 When it has been merged by GitLab, I need to switch to the current master to do a build, locally.当它被 GitLab 合并后,我需要切换到当前 master 在本地进行构建。

My workflow is this:我的工作流程是这样的:

  • Switch to master转主
  • Pull from remote (--ff-only)从远程拉取(--ff-only)
  • Remove stale remote tracking branches删除陈旧的远程跟踪分支
  • Also remove their local tracking branches同时删除他们的本地跟踪分支

There's also a client-side tool that watches the code directory and updates some files (CSS, JavaScript).还有一个客户端工具可以监视代码目录并更新一些文件(CSS、JavaScript)。 When it sees a change in the first step (switch to master), I first need to wait for it to finish before going on (to avoid confusion).当它看到第一步发生变化(切换到master)时,我首先需要等待它完成再继续(避免混淆)。 If there's a difference between the issue branch and the old master, there's a good chance that the difference will disappear when updating master (as that issue branch is now merged).如果 issue 分支和旧 master 之间存在差异,那么在更新 master 时差异很可能会消失(因为该 issue 分支现在已合并)。

I'm looking for a way to switch to the already-updated master branch in one step.我正在寻找一种方法来一步切换到已经更新的 master 分支。 How can I do that with a git command?我如何使用git命令执行此操作? I want to bundle up all these actions in a batch file to avoid repeating all those manual steps in TortoiseGit every time.我想将所有这些操作捆绑在一个批处理文件中,以避免每次都在 TortoiseGit 中重复所有这些手动步骤。

This question is different from the suggested one in that the local master branch already exists.这个问题和建议的不同,本地master分支已经存在了。 I'm not switching to a new branch from a remote, but to a branch that already exists and it just behind the remote .我不是从远程切换到一个新分支,而是切换到一个已经存在的分支,它就在远程后面

TL;DR长话短说

Unless you write your own script (or use a Git alias to run multiple commands and/or scripts), you can't get this down to a single command, but you can get closer.除非您编写自己的脚本(或使用 Git 别名来运行多个命令和/或脚本),否则您无法将其简化为单个命令,但可以更接近。 See the long section for many caveats: the biggest one is that it assumes you're not already on master when you do it.请参阅许多警告的长部分:最大的一个是它假设您在执行此操作时还没有master If you are, the second step won't work (see the long section for what will).如果是,则第二步将不起作用(请参阅详细部分了解会发生什么)。

git fetch -p &&
    git fetch . refs/remotes/origin/master:refs/heads/master &&
    git checkout master

will take care of the first three bullet points—not in the same order—with a single work-tree-updating git checkout step .将通过单个工作树更新git checkout step处理前三个要点(顺序不同)。

(Note that I split this into three lines for posting purposes, but as a Git alias using ! , it's really all one big line.) (请注意,出于发布目的,我将其分成三行,但作为使用!的 Git 别名,它实际上是一大行。)

Long

There are several approaches, including actual, literal batch files (shell scripts on Unix-like systems, or.BAT files, or whatever) and aliases (as suggested by Joe in a comment ).有几种方法,包括实际的文字批处理文件(类 Unix 系统上的 shell 脚本,或 .BAT 文件,或其他)和别名(如Joe 在评论中所建议的那样)。

There's also a client-side tool that watches the code directory and updates some files...还有一个客户端工具可以监视代码目录并更新一些文件......

This is... not necessarily a good idea, let's say.这……不一定是个好主意,比方说。 :-) :-)

While git checkout master runs, it's changing various files.git checkout master运行时,它正在更改各种文件。 Let's say that for some reason, it changes one of several files that the watcher watches, but then it pauses for a few minutes (or seconds, or microseconds, or some unit of time anyway).假设由于某种原因,它更改了观察者观看的几个文件之一,但随后它暂停了几分钟(或几秒、几微秒,或无论如何是某个时间单位)。 While it is paused, the watcher tries to combine the multiple files that are now out of sync.暂停时,观察者会尝试合并现在不同步的多个文件。

Maybe this is OK and self-correcting when Git un-pauses and finishes the checkout—but it might be better if you could make sure the update only happens when the checkout is done.当 Git 取消暂停并完成结帐时,这可能是 OK 和自我更正 - 但如果您可以确保更新仅在结帐完成时发生,则可能会更好。

That aside, let's take a look at this particular series of commands, and be very concrete about which Git command you're using:除此之外,让我们看一下这个特定的命令系列,并非常具体地说明您正在使用哪个 Git 命令:

  • Switch to master转主

I assume this is git checkout master .我假设这是git checkout master

Pull from remote (--ff-only)从远程拉取(--ff-only)

I assume this is git pull origin master --ff-only or perhaps just git pull --ff-only .我假设这是git pull origin master --ff-only或者可能只是git pull --ff-only

  • Remove stale remote tracking branches删除陈旧的远程跟踪分支

I'll assume for now that this is git fetch --prune .我现在假设这是git fetch --prune If you are doing something different, you should include that in your question.如果您正在做不同的事情,则应将其包含在您的问题中。

  • Also remove their local tracking branches同时删除他们的本地跟踪分支

If I understand what you mean, this requires a script.如果我明白你的意思,这需要一个脚本。 Note that this is somewhat dangerous: suppose you have your own branch X on which you are doing development.请注意,这有点危险:假设您有自己的分支X ,您正在其上进行开发。 This X is not related to anyone else's X .这个X与其他任何人的X无关。 Then someone creates their own X —using the same name—and sends it to the machine from which you git fetch .然后有人创建了他们自己的X使用相同的名称——并将其发送到你git fetch的机器。 You now have origin/X .你现在有了origin/X Then they delete their X (because they're done with it) and delete origin/X .然后他们删除他们的X (因为他们已经完成了)并删除origin/X If you now have your script delete your X , because origin/X went away, that would probably be bad.如果你现在让你的脚本删除你的X ,因为origin/X消失了,那可能很糟糕。

If you only delete your X when it explicitly has origin/X set as its upstream, this particular case won't occur—but if someone accidentally deletes your origin/X thinking it was their origin/X , the same problem crops up again, and this time that particular protection does not work.如果您仅在X明确将origin/X设置为其上游时才将其删除,则不会发生这种特殊情况——但如果有人不小心删除了您的origin/X并认为这是他们的origin/X ,同样的问题会再次出现,而这次特定的保护不起作用。

Anyway, with all that aside, let's look at the variant I suggested above.无论如何,撇开所有这些不谈,让我们看看我上面建议的变体。

git fetch -p

This updates all your origin/* names, 1 including origin/master , without affecting any files in your working tree.这会更新您所有的origin/*名称, 1包括origin/master ,而不会影响工作树中的任何文件 The -p is short for --prune , so it deletes any origin/* names that no longer have a corresponding branch in the Git over at the URL stored under the name origin . -p--prune的缩写,因此它会删除在 Git 中不再具有相应分支的所有origin/*名称,这些名称存储在名称origin下的 URL 中。


1 I assume here that you have only one remote , which is named origin . 1我在这里假设您只有一个遥控器,名为origin If you have more than one remote, use git fetch origin -p to make sure you're fetching specifically from the one named origin .如果您有多个遥控器,请使用git fetch origin -p确保您专门从名为origin的遥控器中获取。 I also assume you have not configured your Git to be a single-branch clone.我还假设您没有将 Git 配置为单分支克隆。


git fetch. refs/remotes/origin/master:refs/heads/master

This rather magic-looking command tells your Git to call itself up.这个看起来很神奇的命令告诉你的 Git 调用它自己 That is, the special name .也就是特殊的名字. refers to your own Git repository .指的是你自己的 Git 仓库 We are using this to trick your Git into fast-forwarding your master branch based on your updated origin/master .我们正在使用它来欺骗您的 Git 根据您更新的origin/master快进您的master分支。 The final argument is what does this: we say to your Git: OK, my Git, when you talk to that other Git, find out what commit its refs/remotes/origin/master identifies.最后一个论点是这样做的:我们对你的 Git 说:好的,我的 Git,当你与另一个 Git 交谈时,找出它的refs/remotes/origin/master标识的提交。 Then, if that's a fast-forward operation, update my refs/heads/master to match.然后,如果这是一个快进操作,请更新我的refs/heads/master以匹配。

Of course, the "other Git" your Git is talking to is itself—so this means fast-forward my master from my origin/master .当然,你的 Git 正在与之交谈的“其他 Git”就是它本身——所以这意味着快进 my master从 my origin/master 2 It's roughly equivalent to: 2大致相当于:

git checkout master && git merge --ff-only origin/master && git checkout -

except that no actual checking-out occurs: no files in your work-tree change.除了没有实际签出发生:工作树中的文件没有更改。


2 You might wonder why some of these use origin/master and some use refs/remotes/origin/master . 2您可能想知道为什么其中一些使用origin/master而另一些使用refs/remotes/origin/master The longer one is just the full spelling of the name.较长的只是名称的完整拼写 When using git fetch , it's wise to use the full spellings.使用git fetch时,最好使用完整拼写。 In fact, in general, in scripts, you might want to use full spellings more often, but specifically git fetch can become confused if the other Git you talk to accidentally has both a branch and a tag with the same name, for instance.事实上,一般来说,在脚本中,您可能希望更频繁地使用完整拼写,但特别是git fetch可能会变得混乱,例如,如果您与之交谈的另一个Git 不小心同时具有同名的分支和标签。 So I'm illustrating the full names with git fetch .所以我用git fetch来说明全名。 You'll use it to talk to your own Git, so if you don't mix up your tags and branch names or otherwise create ambiguity, you won't actually need the full names.您将使用它与您自己的 Git 通话,因此如果您不混淆标签和分支名称或以其他方式造成歧义,您实际上不需要全名。 But it's a good habit with git fetch .但这是git fetch的好习惯。


The above fails if you're on your master如果你在你的master身上,上面的失败

The git fetch command will refuse to fetch into whatever branch name you have checked out. git fetch命令将拒绝提取到您签出的任何分支名称。 So if you are on master , this git fetch.所以如果你master上,这个git fetch. trick will fail.技巧会失败。

In a way, this is OK!在某种程度上,这没问题! If you are on your master , what you should do instead is run:如果你你的master上,你应该做的是运行:

git merge --ff-only origin/master

or anything equivalent.或任何等效的东西。 This is what your git pull --ff-only does: first it runs git fetch (without the -p and limited to fetching only the other Git's master );这就是你的git pull --ff-only所做的:首先它运行git fetch (没有-p并且仅限于仅获取其他 Git 的master ); then it runs git merge --ff-only .然后它运行git merge --ff-only

A more complete version更完整的版本

A more complete version of this sequence, then, is to first check: Which branch am I on?那么,这个序列的一个更完整的版本是首先检查:我在哪个分支? To do that, you can use either of two Git commands:为此,您可以使用两个 Git 命令之一:

git rev-parse --abbrev-ref HEAD

or:要么:

git symbolic-ref --short HEAD

Both of these will print master if you are currently on your own master branch.如果您当前在自己的master分支上,这两个都会打印master The difference between them is what they do if you're on no-branch-at-all: eg, in the middle of a rebase, when you are in "detached HEAD" state. In that case, the second command—the git symbolic-ref one—errors out, while the first one just prints HEAD .它们之间的区别在于它们在完全没有分支的情况下会做什么:例如,在 rebase 的中间,当您处于“分离的 HEAD”state 时。在这种情况下,第二个命令 - git symbolic-ref出错了,而第一个只是打印HEAD

If you'd like to avoid doing any of this when in such a state, use the second command and check for failure.如果您想避免在这样的 state 中执行任何这些操作,请使用第二个命令并检查是否失败。 Otherwise, use the first one.否则,使用第一个。 I'll illustrate just the first one here:我将在这里仅说明第一个:

if test $(git rev-parse --abbrev-rev HEAD) = master; then
    # already on master - use alternative strategy
    git fetch -p && git merge --ff-only refs/remotes/origin/master
else
    # not currently on master: use fancy tricks to update
    git fetch -p &&
        git fetch . refs/remotes/origin/master:refs/heads/master &&
        git checkout master
fi

The above, while untested, should be suitable as a shell script.以上虽然未经测试,但应该适合作为 shell 脚本。 If you have Git installed, you have the ability to run shell scripts—or you can turn the above into a very long Git alias, using !如果你安装了 Git,你就可以运行 shell 脚本——或者你可以把上面的变成一个很长的 Git 别名,使用! and the appropriate set of semicolons.和适当的分号集。

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

相关问题 如何重置整个Git存储库,而不只是重置“ Master”分支,以匹配Remote? - How to reset the entire Git repository, and not only the “Master” branch, to match Remote? GIT:如何使用 git 命令获取从主分支到自定义分支的最新更改? - GIT : How to get latest changes from master branch to the custom branch using git commands? 如何从git导出所有分支更改的文件与本地主文件相比 - how to export all branch changed files compared to local master from git 如何将主分支文件夹添加到github页面? - How to add master branch folder to github pages? 如何将master合并到github中的Windows分支中? - how to merge master into branch in github for windows? 在远程计算机上运行批处理文件以更新git分支 - Run a batch file on a remote computer to update a git branch 如何将更改从master转移到Feature分支 - How can I get changes from master into feature branch 如何使“git branch”尊重Linux上的“core.ignorecase”标志? - How to make “git branch” respect the “core.ignorecase” flag on Linux? 文件夹大小写在分支交换机上没有改变 - Folder capitalization not changing on branch switch 检测Redis的主数据库故障转移并自动将从服务器切换为主服务器? - Detect Redis's master db failover and auto switch slave to master?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM