入职了几个月,都是在 iterm ssh 到服务器,然后开 emacs 写 c++,然后另外开一个 terminal 处理 git 相关的问题。一直听说过 magit,但尝试去使用新的东西总是不那么容易了。上个礼拜,让自己逐步将 git 工作流迁移到 magit 中。这几天的体验越来越好。 特开一贴哈哈。
最好是再分享一下你的magit工作流,不然显得很苍白
好的,我今天找时间整理整理发送,昨天有事哈哈
magit 是我还在坚持用 emacs 的唯二原因之一(另一个是 org mode)确实太好用了,整个 git 的工作流从开发到提交,push 一气呵成,再加上 magit-forge 对 github 的支持很完善,创建 PR,审查 PR 合并 PR 也很方便,非常赞
这个文档,常用用法总结挺详细的 ~ 有需要的参考一下
magit 算是emacs的killer application了,支持楼主总结自己的体验
我算是个半吊子magit使用者吧,我觉得magit特别好的一点是,它每一次使用的时候弹出来的选项都是和git 命令行是一一对应的, 你不用去猜它这个名字到底对应的是命令行的哪个选项,这样我还接触到了不少git的新的各种神奇选项,而且因为每次使用都知道命令行选项对应的是啥,不至于脱离了magit满眼抓瞎不会使用命令行了😂
有没有跟magit一样好用的svn客户端?
有个大概叫 git-svn 的插件,这样本地是git仓库也能用 magit 来用。
我知道git-svn,但我们公司用的是一个巨大无比的仓库,而且必须完整checkout出来才能编译,所以没办法使用git-svn。
svn真没有这么好用的客户端,现在凑合用着自带的vcs,或者dsvn。以前还有个psvn
用 SVN 不也得全部 checkout 吗?用 git-svn 也一样啊,也同样可以只从 HEAD checkout,不用走一遍历史记录了。
用 git-svn 也一样啊,也同样可以只从 HEAD checkout,不用走一遍历史记录了。
是类似 git clone --depth=1 这种吗?这样产生的shallow repo不是不能commit吗?
magit的缺点是慢
normal workflow
主要记录最近1-2周在 magit 上完成的一些操作,以及一些简单的想法。 magit 有两个特点比较显著,一是绝大部分操作都是一个 magit-status emacs buffer 中发起,一是几乎所有的地方如果你觉得它是可以按 RET 的那它大概就可以,并且能达到你想要的效果。这两点在下面会有介绍。
magit-status buffer 是指:
remote 交互
前提是已经有了一个 git repo.和 remote 的交互一般如下:
- fetch origin:
f
- push origin:
P
这两个还是比较简单的。
branch
- 根据当前分支创建一个新的分支,然后进行开发,或者切换到一个已经有的分支:
b
后选择参数
normal manipulate
这里是实际开发中会涉及的操作,根据开发的不同阶段我用到了如下操作:
- 修改了一些代码后,需要提交:
- stage:
s
- unstage:
u
- commit:
c
,还可以 amend、reset author 等 - stash:
z
,不多介绍 - (optional): 在自己的分支上进行 feature 开发时 commit 提交比较随便,一是 message 自己懂就行二是可能有一大堆 commit,因此正式提交前我会进行 squash 一下,即多个 commit id 压成一个:
r
+i
, 它是开了一个新的 buffer 用于选择我们要压哪些 commit,很好用。比如我新加了 commit-1 和 commit-2,在进行上诉操作后会得到如下 buffer,可以移到 commit 1 那然后C-c C-c
即可。
2.(optional) 在 CI 上发现我的分支 unmergable
- rebase:
r
+e
可以选择 rebase 到哪个分支。比如我的branch2rebase
和main
同时修改了CMakeLists.txt
,此时我在 branch2rebase 上进行 rebase 操作,它提示有冲突,我们点 unstage 部分
3.(optional) 有时候会想将当前分支强制同步到另一个分支: reset X
,记得选择 hard.
4.(optional) 比如我突然不想 track 某个文件了,则光标移到那一行 => K
甚至 k
直接 delelte
这里有几个我觉得很好的体验:
-
stage/unstage 时,不是以 file 为单位而是 diff chunk:
-
大部分我们认为能 RET 的地方都可以 RET 且和我们预期效果一致:比如我看到我改了
Access.h
, 那我想跳转过去看一看,很自然的会按一下 RET,事实也和我们预期一致。 -
magit-status buffer 作为 magit 核心 buffer,里面展示了我们想要的大部分信息,例如 staged/unstaged、commit、current branch 等等,我们是基于这个已有信息做操作,而 terminal 下我们即使是展示信息也得敲一下
git status
(我知道可以 alias),但就感觉 magit 这个真的很方便。
文件查看、编辑相关
我觉得这里是 magit 和 emacs 融合更紧密的地方,下面挨个说。
-
在 A branch 开发的时候,想临时看下 B branch 某个文件 这如果是我以前的 terminal-based git 工作环境,我甚至得 stash->checkot->view and copy file->checkout back. B 分支的文件我得放在一个临时文件中,然后在 emacs 中开两个 buffer 同时看。 但是 magit 提供了
magit-find-file
,我们可以比如绑定到C-x m f
,它可以指定访问某个分支中某个文件,且是放到一个临时的 buffer,只能说极其好用
-
在代码 MR 整理提交阶段,肯定会碰到想看两个文件 diff 的时候,展示 diff 本身不难,但是要融入编辑性,就是 magit 牛的地方:
编辑性是指,在进行 diff 的时候,我可以 buffer1 看我文件 diff 内容,一边看这个文件真实的内容,然后做修改。具体是通过 d
+ r
完成的,他需要指定 commit range,是 commitstart…commit-end 的格式。 当然 d
配套的 diff 功能很多,例如 diff 当前 staged files 等等,但我目前没用到。
杂项
git blame
比如我要看当前区域的代码是 who/which commit 提交的。这种都是临时性的需求,因此它是通过特殊 command(C-c M-g b
) 以开关的形式操作的(不然看起来太乱了):
当我想看看某个 commit 到底改了啥的时候,我下意识的按了 RET,然后真的跳转过去了,NB
submodule
我最近做的项目有一大堆 thirdparty 依赖,terminal 中处理起来不友好,但是 magit 就很不错 注:所有操作基于 prefix o
. 主要问题有如下几个:
- 有哪些 submodule? =>
l
它会跳转进入一个临时 buffer 展示 submodule,神奇的是,我们依然可以通过 RET 转到 submodule 内部的 magit-status! - 添加修改整个 submodule,不过我目前没这个需求,项目已经有雏形了。
- 在主 repo 多个分支切换后,submodule 版本不对应问题(dirty)
-r
+u
表示将 submodule 版本切换到我主 repo 记录的版本 - submodule untracked files 比如由于一些错误/意外操作,我 git status 显示 submodule 有 untracked contents,此时进入那个 submodule 的 magit-status buffer,直接对想删除的 file 按
k
即可删除,要批量达到git clean -fd
可以通过!!
发起外部 git command 完成,也很方便。
如果觉得 magit 好用,还可以在 github 上给那个作者一些 sponsorship 哈
没问题的,我经常在 branch 或者新的仓库上这么用,git svn fetch -r <revision>
, 自己在自建的仓库试试就知道了。
其实还好,服务器上配置一般都还可以,我目前项目使用卡顿基本没有,项目也有中等规模了
如果是在server(比如E5-2650)上对linux kernel进行magit的命令,这时候magit的性能是很难忍受的,我选择一边magit一边摸鱼了。
linux kernel 目前100多万个 commit,这个级别的 commit 规模卡没办法了吧