git如何切换分支命令?
发布网友
发布时间:2022-04-22 10:07
我来回答
共1个回答
热心网友
时间:2023-10-04 23:16
作为程序员的我们应该都有一个感受,一旦进入某个项目,从开发,到发布生产,到hotfix,到后期维护,那基本都有你的份,正在开发某个feature,老板突然跳出来说让你做生产商的hotfix更是家常便饭,面对这种情况,使用Git的我们通常有两种解决方案:草草提交未完成的feature,然后切换分支到hotfix
gitstash|gitstashpop暂存工作内容,然后再切换到hotfix
第二种方式较第一种还好很多,可是面对下面这些场景,stash依旧不是很好的解决方案
我们面对的场景
正在main分支上跑很长时间的测试,切换到hotfix或feature,测试就会中断
项目非常大,频繁地切换索引,成本非常高
在几年前release的旧版本,设置和当前不一样,IDErestructure适配切换也会带来很大的开销
切换分支,需要重新设置相应的环境变量,比如dev/qa/prod
需要切换到同事的代码,帮助调试代码复现问题
有的同学想到,gitclone多个repo不就可以了吗?这是解决上述问题的一个方法,但背后同样隐藏着很多问题:多个repo的状态是不好同步的,比如没办法快速cherry-pick,一个repocheckout的分支,另外一个repo需要重新checkout
githistory/log是重复的,当项目历史非常长,.git文件夹下的内容是非常占用磁盘空间的
同一个项目,多个repo,不易管理
那如何做才能满足这些特殊场景,又不出现上述这些问题呢?git-worktree
其实,这是Git2015年前就开始支持的功能,却很少有人知道它,git-worktree的使用非常方便,在终端输入:gitworktree--help
就可以快速看到帮助文档说明:
用简单的话来解释git-worktree的作用就是:仅需维护一个repo,又可以同时在多个branch上工作,互不影响上面红色框线命令有很多,我们常用的其实只有下面这四个:gitworktreeaddgitworktreelistgitworktreeremove
gitworktreeprune
在展开说明之前,需要和大家普及两个你可能忽视的Git知识点:默认情况下,gitinit或gitclone初始化的repo,只有一个worktree,叫做mainworktree
在某一个目录下使用Git命令,当前目录下要么有.git文件夹;要么有.git文件,如果只有.git文件,里面的内容必须是指向.git文件夹的
第二句话感觉挺绕的,下面用例子说明,就很容易明白了gitworktreeadd
当前项目目录结构是这样的:.└──amend-crash-demo1directory
cdamend-crash-demo运行命令gitworktreeadd../feature/feature2_amend-crash-demogit:gitworktreeadd../feature/feature2PreparingworktreeHEADisnowat82b8711addmainfile
重新看目录结构.├──amend-crash-demo└──feature└──feature23directories
该命令默认会根据HEAD所在的commit-ish创建一个名为feature2的分支,分支磁盘位置如上面结构所示cd../feature/feature2/会发现,这个分支下并不存在.git文件夹,却存在一个.git文件,打开文件,内容如下:gitdir:/Users/rgyb/Documents/projects/amend-crash-demo/.git/worktrees/feature2
到这里,你再理解一下上面的知识点2,是不是就清晰许多了呢?接下来,你就可以在feature2分支上做一切你想做的内容了,和mainworktree互不干扰一般情况下,项目组都有一定的分支命名规范,比如feature/JIRAID-Title,hotfix/JIRAID-Title,如果仅仅按照上面命令新建worktree,分支名称中的/会被当成文件目录来处理gitworktreeadd../hotfix/hotfix/JIRA234-fix-naming
运行完该命令,文件目录结构是这样的.├──amend-crash-demo├──feature│└──feature2└──hotfix└──hotfix└──JIRA234-fix-naming6directories
很显然这不是我们想要的,这时候我们就需要-b参数的支持了,就像gitcheckout-b一样执行命令:gitworktreeadd-bhotfix/JIRA234-fix-naming../hotfix/JIRA234-fix-naming
再来看一下目录结构.├──amend-crash-demo├──feature│└──feature2└──hotfix├──JIRA234-fix-naming└──hotfix└──JIRA234-fix-naming7directories
进入JIRA234-fix-naming目录,默认是在hotfix/JIRA234-fix-naming分支上
worktree建立起来很容易,不加管理,项目目录结构肯定乱糟糟,这是我们不想看到的,所以我们需要清晰地知道某个repo都建立了哪些worktreegitworktreelist
所有的worktree都在共用一个repo,所以在任意一个worktree目前,都可以执行如下命令来查看worktree列表gitworktreelist
执行完命令后,可以查看到我们上面创建的所有worktree信息,mainworktree也会显示在此处/Users/rgyb/Documents/projects/amend-crash-demo82b8711/Users/rgyb/Documents/projects/chore/chore8782898/Users/rgyb/Documents/projects/feature/feature282b8711/Users/rgyb/Documents/projects/hotfix/hotfix/JIRA234-fix-naming82b8711/Users/rgyb/Documents/projects/hotfix/JIRA234-fix-naming82b8711
worktree工作做完了,也是要及时删除的,否则也会浪费很多磁盘空间gitworktreeremove
这个命令很简单了,worktree的名字叫什么,直接就remove什么就好了gitworktreeremovehotfix/hotfix/JIRA234-fix-naming
此时,分支名弄错的那个hotfix就被删掉了/Users/rgyb/Documents/projects/amend-crash-demo82b8711/Users/rgyb/Documents/projects/chore/chore8782898/Users/rgyb/Documents/projects/feature/feature282b8711/Users/rgyb/Documents/projects/hotfix/JIRA234-fix-naming82b8711
假设你创建一个worktree,并在里面有改动,突然间这个worktree又不需要了,此刻你按照上述命令是不能删掉了,此时就需要-f参数来帮忙了gitworktreeremove-fhotfix/JIRA234-fix-naming
删除了worktree,其实在Git的文件中,还有很多administrative文件是没有用的,为了保持清洁,我们还需要进一步清理gitworktreeprune
这个命令就是清洁的兜底操作,可以让我们的工作始终保持整洁总结
到这里,你应该理解,整个git-worktree使用流程就是下面这四个命令:gitworktreeaddgitworktreelistgitworktreeremovegitworktreeprune
你也应该明白gitworktree和gitclone多个repo的区别了。只维护一个repo,创建多个worktree,操作间行云流水我的实践:通常使用gitworktree,我会统一目录结构,比如feature目录下存放所有feature的worktree,hotfix目录下存放所有hotfix的worktree,这样整个磁盘目录结构不至于因为创建多个worktree而变得混乱在磁盘管理上我有些强迫症,理想情况下,某个repo的worktree最好放在这个repo的文件目录里面,但这就会导致Gittrack新创建的worktree下面的所有文件,为了避免Gittrackworktree的内容,来来回回修改gitignore文件肯定是不合适的,