magit 和 emacs 结合起来有很多方便的地方,而且偶尔能学到新的东西。
比如 magit 很多 buffer 都是可以操作的。举个例子,点开某个 commit diff,按 u
可以 revert hunk,按回车可以跳转到那个 commit 对应的这个文件。总之就是很多小细节用起来非常的自然,不用可以去记
git设计得太复杂了。光用命令行根本记不住。
但没辙,这玩意流行起来了,连 FreeBSD 都在用 Git 管理代码(他们的项目甚至还会用 GitHub Actions)。
还是需求驱动的问题,开源项目每个人需求都不同,参数不断增加就变成这样了。
我只需要一个非常非常少的子集。加起来也就是个八个命令就行了。
其他人可以也弄一个子集。很多功能一般也用不着
我讲一个最近发现的很喜欢的细节。我有时候本地会有比较多的变更,而commit的时候只想提交指定文件里的一部分hunk。
如果使用CLI,那我需要使用git add -p xxx
,CLI会自动分hunk,然后按hunk问我如何处理。如果并不想提交整个hunk,只想提交里面的某几行,那就得split,然后重复前面的步骤。
而在magit里,我只需要mark set,选中想提交的几行然后stage即可。
后者比前者优雅太多了。
magit 和 CLI 不是同一个抽象层的东西,不太好比较,magit 是对部分 CLI 提供的命令接口用交互式 UI 做封装,git 里很多操作是需要 UI 设计的,而且感觉这方面探索远没有结束(也就是我还期待有更好的交互方式出现)。写代码用的最多的是 diff 比较之后局部代码块的提交和撤回,大部分 IDE 或者基于 git 的UI程序重点也是在这块。magit 只是依托 emacs ,以快捷键为主。横向和 vscode 比较的话,我更喜欢vscode 的方式,因为提交前会打开左右两个 buffer,两个 buffer 都是完整的源代码,左边是修改前的,右边是修改后的,只有有差异的部分是颜色高亮的,然后两个 buffer 中间有一个箭头 → 和一个加号 , 点击箭头就是用修改前的内容覆盖修改后的(所以是撤回),点击加号是添加到暂存库(也就是右边覆盖左边buffer),如下形式:
无论点击箭头还是加号,版本上的差异都会消失,所以点击后高亮就会消失。 我觉得这点比 magit 的方式更直观,也能精确到每个小的 hunk, 这种 UI 直接改变我写代码的习惯,甚至可以直接在右侧 buffer 里修改,写代码同时看到修改前和修改后代码,但你的注意力只会关注那些差异的部分,不容易乱,能把注意力引导在少量的但重要的信息上的工具就是好工具。
但 git 作为一个基于时间片的数据库,里面还有大量的增删改查接口,IDE 更多是面向写代码层面的。 如果你想研究某个项目,希望从第一次 git commit 开始看,每次只看差异部分,但很多提交都是些 bug fix 或者修改 readme,这时候就需要在整个提交树上做标记(自己加注释,根据提交者或提交信息过滤)然后在几个关键的提交之间反复比较差异,这就需要另外一种可视化或者交互方式了,IDE 里集成起来可能代价太高,目前我用的是 gitkraken ,但其实还是能感觉到一些不足,用的也不是很熟,就不展开说了。
另外 magit status 和 git status 本身就是不同的命令,后者默认只是显示出有差异的文件名,前者除了文件之外,还把具体差异的diff 代码也显示了出来,所以执行了更多命令,如果代码量大,修改多,效率自然会更低。
建议你研究一下 emacs 内置的 ediff,非常强大
magit 是有集成 ediff 的,在 magit status buffer 里光标移动到代码差异部分,按 e 就会弹出 ediff,然后也能出现左右两个 buffer 比较的视图,但可视化效果没有那么流畅 (似乎没法在不同版本之间边修改边更新高亮),而且 maigt+ediff 连招里面的一套按键,对于大部分人来说是优点,但对我却是问题:
主要原因是,我是 evil用户,以下图里的按键
全都是复用 evil 里常用的按键,但 magit status 里更大问题在于一个buffer里不同 section 下同一个按键对应不同功能,比如放在diff区域按 e 是ediff,放在标题上又是 evil-forward-word-end, 这导致我在 diff 区域有时候想用 e 移动到句子里某个词上,去复制上个版本的内容时,结果先弹出 ediff buffer,而 ediff buffer 里居然又是一套新的按键(还有一个专门 ediff control panel来接管按键),导致我经常在 magit status 里因为按错按键而打开一堆ediff buffer ,然后要用 ediff 的专用按键去检查、退出,为了提交个代码,我得切换三四套按键体系,实在心累,这是我几乎不用 magit 的直接原因(我之前大部分 org 笔记,emacs 配置等个人项目都是用 magit,但后面直接绑定快捷键用 vscode 打开项目,专门用来对比 git 差异和提交代码 )。
另外,手动定位特定的 hunk 、打开 ediff 然后检查、关闭、提交commit,和 vscode 这种一键展示差异和差异上下文,并且中间用两个直观的按钮来刻画操作是很不一样的,这也是我说这种模式能培养习惯的原因,不是 单纯的 diff 比较视图的能力,是这一套交互方式的简单、有效和无副作用性。
不太明白你说的更新高亮是什么,但是在一边修改然后应用是可以的
你可以自己改成一致的
进入 ediff 之后可以遍历所有的 diff,不用一个一个定位
这个我看了一下,ediff 也是可以的,就是左边是修改前的代码(上一次 commit的代码),右边是目前工作区代码,然后每次修改后,差异都会重新高亮出来。这部分不是核心,只是有的时候提交前可以临时修改然后即时比较差异。
这个要等待个人需求和有足够的时间了。用 vscode 提交代码的时候都是鼠标操作,然后完全图形化点几个按键(这方面不像是编辑操作,涉及精确定位、修改、复制粘贴、多行编辑等等,所以需要一套按键模式。但修改完提交代码时,都是一眼看一下各个 hunk 的区别,知道自己改了些什么,如果功能比较统一,commit message 比较好写就提交,所以个人感觉 git 里最常用的操作不需要太多键盘交互,图形化+鼠标就很好了),更复杂的 git 命令都记录在 org 里,类似常用命令行速查表,需要的时候直接查出来复制执行就可以了,再复杂的就问 AI 了,所以目前没有动机去定制。
这里指的是,打开 magit status 后需要手动再定位到一个文件差异上,然后打开 ediff buffer (这个buffer 默认是覆盖了 status buffer),检查完差异后又要返回到 magit bufer 去按 cc 提交,然后弹出一个新 buffer 写 git message。 但 vscode 里是,左侧有一个 nerd tree 形式的侧边栏充当 magit status buffer, 这个buffer里包括 commit 提交框,点击文件后 diff 双栏结构直接就在右侧 window 并列显示,个人更喜欢这种文件、diff 信息,commit 填写框都在一个视图里情形,所有信息一目了然,当然 magit 也可以定制,但这和上一条一样,目前还没有足够多时间和足够多已有问题促使自己去定制。
我就是因为evil跟很多emacs原生窗口快捷键冲突才放弃evil的,并不是所有插件都能很好的兼容evil,自己弄又很麻烦,还是用原生的emacs快捷键更方便
我目前还是用内置的 vc 配合 cli,vc可以覆盖我使用场景的80%,有些自己常用但vc没有的就写个elisp函数,很够用了。最开始也是靠 magit 学会了大部分的 git,magit 的问题是很多操作我用不到,用的到的为了保证一致性layer藏的过深,也不是对于我最舒服的,不如用elisp定制。
我想着的也是,如果以后定制也从内置的 vc 结合 ediff 着手,不太会想去改 maigt
我是从 vim 转到 emacs,主要是为了用 evil+org+roam+jupyter 的,不在这个核心需求里的包有冲突的话,基本都弃用或者只是用很少一部分不冲突的功能
我在windows上用git extension比较多,鼠标点点比较舒服。 怎么设置magit-status的打开单git commit的diff像git extension那样。 我看git extension查看单个git commit的diff,命令是这样。
"C:\Program Files\Git\bin\git.exe" -c color.ui=never -c diff.submodule=short -c diff.noprefix=false -c diff.mnemonicprefix=false -c diff.ignoreSubmodules=none -c core.safecrlf=false diff --find-renames --find-copies --unified=3 "d2e38138c25eb43fcb00b3fb55339578f5bb49ba" "36343bed39c48632b3df55fa280494ebf20038a1" -- "Utils.java"
- magit-cherry-donate:这个太好用了,可以选中某个区域的 commit 直接把它们嫁接到别的分支上,很适合在其他分支开发时想选中部分内容合入主线。
大佬这个怎么用的,没用过,我一般cherrypick都是一个一个的用l o
,A A
操作。
在任意界面选中某个范围连续的 commits,按下 A
可以看到 dispatcher 界面:
“Apply elsewhere” 下面有 Donate 一项,按下 d
,选择一个其他 branch 就可以了,这样你选中的 commits 就会移动到那个 branch 上了。