快速切换分支的 Git 最佳实践

26

我有多个活跃分支需要同时处理。显然,我可以创建两个工作目录,每个目录一个独立的分支。这是不需要执行“提交”和“检出”以切换分支的唯一方法吗?

6个回答

22

如果您需要暂时切换分支,git stash是很有用的,但请记住,提交不需要永久保存;您可以做临时提交以便稍后回滚。

因此,我的建议是,如果要长时间切换,请使用git commit,因为根据您的记忆力,stash可能很容易被遗忘、丢失等。

[In MyBranch]
>$ git commit -m "WIP: Stuff I was working on."
>$ git checkout AnotherBranch
[Do Stuff]
>$ git checkout MyBranch
>$ git reset HEAD^
[Continue]

既然这是一个关于最佳实践的问题,请记得使用 git stash save 给你的 贮藏 添加有用的信息,否则以后可能会很难找到。


如果您在不同的电脑上工作(例如:在办公室1和办公室2),通过这种方式,您可以提交未完成的工作[在办公室1]并推送到远程,然后稍后您可以在[办公室2]拉取并重置它,进行操作并进行最终完成提交。 :) - kdaShivantha

20

是的,如果您还没有准备好完成当前正在进行的工作,您可以使用git stash而不是commit


1
我之前不知道这个命令。我喜欢它,因为它正是我想要的。只是一个地方可以放置我的东西,直到我真正准备好提交。在过去的一周里,我已经多次提交“snap”,以便我可以更改分支。这让我非常生气,因为其中许多更改很可能会再次更改...与此同时,当我推送时,这些更改将对我的团队公开...其中一些可能会令人尴尬。“stash”需要尽快测试。谢谢! - Richard
2
很高兴能够帮助。正如cweider所指出的那样,重要的是要意识到,只要提交未被推送,您就可以始终重新编写本地历史记录。例如,如果您在要保留的其他提交之间有一个“快照”提交,则可以将其“cherry-pick”到另一个分支中,然后执行“rebase -i”以将其从其他分支中删除。 - dahlbyk

5

git clone通过本地协议,是在同时处理多个分支时的好选择。

我通常会将本地裸仓库克隆为多个副本(每个活跃分支一个副本),并将该裸仓库用作中央集成仓库(因为可以轻松地向裸仓库推送,而不能向非裸仓库推送)。


有关“裸仓库”的解释,请参见https://dev59.com/eUvSa4cB1Zd3GeqPc0C9#2041865。 - VonC
2
人们以前使用 SVN,现在你可以使用 Git 的分支功能,不需要太多本地存储库。这就是 Git 的主要优点。 - Gismo Ranas
4
我同意。我写这个已经超过4年了 ;) - VonC

4

我厌倦了在不同分支之间切换,因此我写了一个更智能的git checkout。将以下代码插入到你的~/.bash_profile中,然后加载它,接着只需使用gch即可切换到上一次使用的分支。

current_git_branch() {
    git branch | grep \* | awk '{ print $2 }'
}
# a smart git checkout, with no args it switches to last branch.
gch() {
    if [ -n "$1" ]; then 
        echo `current_git_branch` >"/tmp/last_git_branch_used.txt"
        git checkout "$@"
    else
        if [ ! -f "/tmp/last_git_branch_used.txt" ]; then echo >&2 "ERROR: Please run gch with 1 argument first."
        else
            echo `current_git_branch` >"/tmp/last_git_branch_used.temp"
            git checkout `cat /tmp/last_git_branch_used.txt`
            mv "/tmp/last_git_branch_used."{temp,txt}
        fi
    fi
}

这仍然是你一年多后解决问题的方式吗?只是好奇,因为我正需要这个。 :) - Matt Passell
1
是的,这个精确的片段仍然在我的bash配置文件中。其中一个缺点是last_git_branch_used.txt没有关于git repo的信息,所以如果你在不同repo的不同分支之间来回切换,这就没那么有用了。但我仍然认为我节省了无数次按键。 - skensell
2
我过去几天一直在使用它,发现它非常方便。我大部分工作都在一个仓库中完成,所以这绝对是我可以接受的限制。顺便说一下,它与zsh一起使用效果很好(这并不奇怪,因为zsh源自bash)。我会与我的团队分享这个工具。谢谢! - Matt Passell
所以我对这个脚本进行了一些改进,将之前切换的分支缓存到项目的.git文件夹中,无论你是否在子文件夹中。https://gist.github.com/spoike/3c84325b2dc35d18bbdf630606c7d034 - Spoike
3
看起来你可以使用git checkout -命令切换到之前检出的分支,这与git checkout @{-1}命令相同。你可以在Git文档中有关分支引用的特殊情况中了解更多信息。 - Spoike

1

如果您正在进行所谓的分支特性开发,如此处所解释的:

http://martinfowler.com/bliki/FeatureBranch.html

你可能还想确保切换数据库模式。Git 可以通过 smudge 和 clean 来帮助实现这一点。这样就可以在本地管理多个数据库了。当你检出一个新分支时,你可以使用 smudge 命令将连接字符串注释为分支名称。如果配置文件在任何时候被提交,它会通过删除连接中的分支名称来进行清理。

欲了解更多信息,请参阅Pro Git book


0
我有一个像这样的Bash函数:
function gitredocommit {
  lastcomment=`git log | grep Date -A 2 -m 1 | tail -1 | sed -e 's/^ *//' -e 's/ *$//' | grep -v Merge`
  if [ -n "$lastcomment"  ]; then
    git reset --soft HEAD^; git add ../; git commit -m"$lastcomment"
  else
    echo "last commit was a merge, won't redo it"
  fi
}

你创建一个新的分支,进行第一次(也是最后一次)提交,然后通过这个分支可以做新的东西并覆盖此提交。如果需要从主分支更新,则使用

git rebase master

当然,这样你的提交总是在分支的顶部。只要你不将分支合并到主分支中,这种方法就有效。


1
“lastcomment=” 这一行是您用来检测提交是否为合并的方法吗? - Andrew C
请使用神奇的水平滚动条查看行尾。 - Gismo Ranas
抱歉,那是我试图表达“那是一种完全疯狂的检测合并提交的方式,它具有可怕的性能影响”。尝试使用git rev-parse HEAD^2代替。 - Andrew C
如果它能工作,那就是好的,不必在计算机科学领域的专家公告上发表才算优秀。无论如何,感谢您的建议,我会检查一下使用它能获得多少皮秒的性能提升。 - Gismo Ranas
2
除了它不起作用。你没有检测到合并提交,而是检测到了单词“Merge”,导致了错误的结果。如果你在一个中等大小的项目上执行 git log(不带 -1),那么你将浪费10秒钟到几分钟的时间。 - Andrew C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接