66 comments

[ 4.3 ms ] story [ 148 ms ] thread
i don't like tuis that much (other than for editing text, i mean), but i also really don't like git's command line interface.

so i've been using forgit, which basically adds a really nice fzf interface for git. it really fits the way i work within a terminal (i'm a heavy fzf user).

https://github.com/wfxr/forgit

I will try this, as I'm always looking for a good git client comparable to magit that I can recommend to non-Emacs users. But I doubt it will be comparable to magit. I started to think about making a TUI client myself, but I very quickly realised a big part of what makes magit good is that it's in Emacs. There are so many points where you need to enter/edit/select text etc. To get the power of magit you'd also need to reimplement Emacs.
Give tig a try also if you don't know it, it's been my git interface for years now.
I've been using `gitui` after lazygit was getting a bit slow with larger repo histories. Its been really solid. The naming on this cargo almost made me mistake it.

Just my opinion but maybe a more unique name would help ?

For commiting, I found fugitive (in neovim) quite good. Staying in my editor to list the changes, and select the hunks to commit is quite nice.

I also found the fugitive git blame useful. I am looking at some code and I can quickly look at the recent changes.

But for looking at the history in details; something I only need to do rarely; I struggled with fugitive. I never managed to use `tig` properly. And I sometimes used `git gui` and `gitk`.

I recently tried (cargo) `gitgui` and I found it intuitive. It might be the one. Time will tell.

Yeah same, but this gitu looks interesting too. Just from the screenshots alone I might like this interface more. Sadly not yet available through brew or nix, I'll wait.
(comment deleted)
Others include lazygit, gitui, git-fuzzy. Lately I think fugitive in Vim is enough for routine work for me lately, though git-fuzzy is great when I remember about it. Doesn't need any installation (just add in path) and acts like a git command so you just run "git fuzzy".
Nice! I tried some months back implementing a “framework” that would allow for implementing Magit-like interfaces for any command (https://github.com/federicotdn/brief) but at the end of the day, implementing bespoke interfaces per-command would probably allow you to better integrate with the command itself.
Magit is built on such a framework. It is called 'transient' an Emacs Lisp library.
The biggest quality of life improvement for me with git is a bash function I wrote that does add all, commit and push in one. Turns out I don’t care about all the granular control it provides 99% of the time, it’s cumbersome:

$ save This is a commit message no quotes

So basically `scp -r` (recursive remote copy).

It's what I call "dumb version control" and I've observed many people not going beyond this with git: https://blog.gpkb.org/posts/git-is-a-version-control-system/

It's better than scp because it stores the commit message and the history, and old versions are immutable.
Well, I'm not sure what kind of commit messages would be possible other than "update" and "new version" etc. if you're committing everything each time.
Wouldn't it be possible to fix a bug then commit that fix?
This is fine for using git as a kind of offsite backup, but I hope you later rebase everything into meaningful commits with proper messages if you're going to share your work with anyone else.
Dunno, I’ve spent countless hours carefully grooming my git commit histories so they make sense and convey a coherent story, just to have them destroyed by some squash zealot at merge time .

“Squash before merge” workflows seem to be more common these days and I have to think it’s mostly a push by people who do not know how to do interactive rebases and history rewrites.

You did the right thing, and I'm sorry this happened to you. May you only have to contribute to non-squashing projects in the future.
I find it has more to do with people (myself included) who interact with git at a PR/MR level.

If your PRs are small and you interact with git a lot using some web portal it sort of pushes you this way.

Squash before merge is fine if you have a project tracker, where you can use the issue as a discussion hub to describe your thoughts. Then you put the issue number in the squashed commit message. The PR can serve as implementation specific documentation and discussion.
I disagree: discussion in a ticket or issue tends to be as disorganized as the random series of commits that are frowned upon in “nice commit history” workflows. It’s just sweeping the mess to another place where it can’t easily be found.

But it’s okay, I gave up trying to convince people. So I’ll just disagree and commit (pun intended).

What's the worth of a commit-message? The code, it's documentation and the associated issue-number is enough information. Or are people just not using their other tools for communicating those things?
Why did you make this commit? What was the reason that made you stage these particular files and their changes and commit them to the repo? What were you trying to fix, add, or change?

I rarely see that documented in comments because it changes constantly, and documentation tends to be for users. An issue number can have that information, but if you're going to be tracking changes in git anyway why not use the system as designed so people don't have to hop to a different system to get a quick understanding of the commit?

> documentation tends to be for users.

There is user documentation and there is technical documentation. Both are very different. Unless you have a lib, framework or such, in which case it's more or less the same.

> but if you're going to be tracking changes in git anyway

Yes, it's a technical system for tracking changes, not documenting those changes on the developer-level.

> so people don't have to hop to a different system to get a quick understanding of the commit?

Because for any meaningful complex product you need to do that anyway. commit-messages are just the bare minimum of ways to document. Though, of course, you can make more use of it, including it in some semi-automatic changelog and such. But usually it's not worth the hazzle.

> tracking changes, not documenting those changes

Documenting changes is part of tracking them. Yes, there is the code itself, but explaining those changes allows for following the development path. Do you expect everyone to read every line of code to understand every commit?

> commit-messages are just the bare minimum of ways to document

Single-line messages, yes. Multi-line commit messages are plenty for commit messages because they let you add more context about the changes.

I'd like to point out that it's possible for there to be multiple commits for a single issue - maybe the first one didn't fix it, or maybe there's multiple components being fixed. Simply pointing back to the issue won't give enough relevant information about each commit, it will simply say what the group of commits as a whole is supposed to do. If it turns out that fixing that issue caused others to occur, then the individual commit messages are going to be more useful for diagnosing the new problem than a single lump issue conversation will be.

I agree that there should be more documentation for a project than just git commits, I just think you're wildly estimating how useful commit messages really can be.

> Do you expect everyone to read every line of code to understand every commit?

Do you expect everyone to read every commit? I get the impression you have the wrong focus.

We do one person per branch with rare exception. When trying to piece together past changes while debugging I basically don’t care what the commit messages are, I use JetBrains’ “show history for selection” in most cases.

Much more useful to me than the messages is the changeset file name highlighting so I can see which files I’ve touched for the thing I’m trying to accomplish right this second. Pushing resets that. So the push is based on “I’m thinking about a new thing now”. Often my commit messages are “x” because there is no cohesion to anything since my last push, I went around making a bunch of nit picks while exploring some code path(s).

If it works for me and my team, it’s the right way. Same for everyone else.

You could solve that with a git alias as well which might be a bit more orderly as it would be defined in the git config. You can prepend the command defined for a git alias with an exclamation mark to run anything (not limited to git subcommands). Last example on this page: https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases
Are you trying to tell me you actually don't review your staged changes and/or commits before you push them?

Also how do you resolve conflicts?

Or is this just your solo project with zero users so you dont have to worry about other people's commits or your own commit's quality?

> Are you trying to tell me you actually don't review your staged changes and/or commits before you push them?

The final review happens in the merge request-view on the forge. There is little reason for local reviewing. Especially when multiple people work on a branch.

> Also how do you resolve conflicts?

Editor.

So you just push shit in and make a review request and only then check if you actually had the correct things in commit(s) and have a descriptive commit message? Yikes
I get the impression that many people here seems to be very challenged to know what they actually do. Do you just randomly work on things, barf out different issues into the same branch at the same time?
Agree. We for example do one branch per bug or new feature. You open a draft PR on GH, review it, then when you think it’s ready open a review and someone else can take a look at the whole branch. The commits serve an auxiliary role in that workflow. I think some people assume everyone uses their exact workflow.
I've been a vim user for so long it doesn't even make sense to do the math to give a year. Around 2013, my buddy at work and I switched to Emacs just to try something different. We only lasted a few months. One thing that I took away from that experience was Magit. I was a CLI user of Git because all the other interfaces just bothered me. When I went back to Vim, I started using fugitive. It wasn't bad, but it just didn't have that same Magit feel that I really enjoyed. I tried the Atom text editor for about a year. It was the best Vim-emulator I'd ever seen at the time. Someone had been working on a Magit clone for it. It reminded me of how enjoyable Magit truly was. Flash forward a couple of years, I'm on NeoVim and someone starts working on NeoGit. I couldn't contain my excitement. It's cool to see someone untangle the experience from any one particular editor.
Have you tried tig? Ultimately I’ve started using that instead and it works great as a magit replacement.

I use it together with Kakoune in daemon mode, so I can jump in and out of files with tig and have the state with buffers remain.

tig is great. One of my favourite features is that you can define your own shortcuts in the global .gitconfig. For example, when I press `=` it creates a fixup commit for the selected commit. That, together with the ability to stage single lines completely changed my workflow.

Recently, I have become a bit lazy and use PyCharm to stage and commit changes. Its diff viewer also supports staging single lines but its better integrated. For example, pressing F4 jumps to the current file/line in the main window.

I love tig. I have an ad-hoc fork of it adding a new window which displays a preview of the selected file in the diff prelude section of the diff window, so I don't have to navigate through the single window. It is very helpful to browse the files in a diff easily. (https://github.com/LucasPayne/tig) I swear I will clean up the fork soon, I just implemented it in whatever way worked.

I do something similar to what you are doing with Kakoune daemon mode, but I work in the shell within a vim context. I have bound "e" in diff/stage views of tig to send a message to the current vim to open a new tab for that file at that line.

I have not tried magit yet but am going to now to at least extract some great ideas from it and somehow get it in my current workflow.

I haven't. I've only heard of it. For a very short period of time I tried to get into LazyGit running in my Vim terminal. I just couldn't make the workflow work for me. You know how it is when it gets into muscle memory, and you really begin to fly? Yeah, LazyGit didn't ever happen. (Not LazyGit's fault obviously).

I may try to play with tig as I'm always looking at different tools. Occasionally I even run into game-changers when trying these things.

LazyGit (and gitui), don't use use the `EDITOR` environment variable to delegate to the editor (e.g., Vim). So the Magit-like workflow (where you freely jump to hunks to edit them and then return to the status view) isn't possible in them.

Tig is the only well-known git TUI that does this, making it the only git TUI that works smoothly with Vim.

Have you tried magit with making it use $EDITOR for commit messages?
I haven't used magit in so many years. Wow...I don't have emacs installed on this machine! (I still keep my configs in my dotfiles though)
How hard would it be to implement commands other than git in this client? Something like "Transient outside of Emacs", not just "Magit outside of Emacs"?
IBM CUA

I really wish 5+ decades ago someone would have established a common user access standard for TUI, like IBM did for desktop (GUI) apps.

TUI would be much more pleasant today if all TUI used the same menu system & keys for common actions (e.g. FILE | EDIT | VIEW and CTRL C for copy / CTRL V paste).

https://en.m.wikipedia.org/wiki/IBM_Common_User_Access

EDIT:

To explain further, just look at how Emacs and Vim use different commands to 'exit'.

Emacs uses "C-x C-c", whereas Vim uses ":q!"

Exiting an app, like copy and paste, is a very common task. Yet there is no standard in how to perform that task in TUI today.

With GUI apps, we have that standard (e.g. FILE -> EXIT or on the keyboard "Alt + F4"). This standard came via IBMs CUA standard.

AFAIK CUA wasn't for GUI apps (i think there was even some DOS-based "demo" that used text mode), some text-based DOS programs used it (the Shift+Ins, etc shortcuts you'd find in Turbo Vision-based programs used CUA).

Also what we often call "CUA" nowadays is actually Microsoft's modifications, even if it was based on IBM's (which AFAIK doesn't have things like Ctrl+V for paste but instead the Shift+Ins i mentioned above).

What? ANSI VT100 standard predates IBM's CUA. In fact, so does the VT220 standard. What's missing?

https://en.wikipedia.org/wiki/ANSI_X3.64

That wasn't for Menu layout and common actions (e.g. FILE | EDIT | VIEW)

ANSI VT100 was for what system interrupt happens when you press "ESC".

The concept of FILE | EDIT | VIEW didn't arrive until GUI's. Maybe ncurses enterprise apps. Probably where IBM came up with it. In terminals, the ANSI standard for keycodes, blocks, drawing, buffers, and cursor positions was pretty well defined. GUIs took over and only recently has the TUI seen some love (outside of text-based games of course).
The standard you refer at is at a lower level in the "stack": it is mainly about how a terminal would handle drawing stuff on screen or how user input will be communicated back to the server.

The CUA standard is at a higher level in the "stack": it is about the user interface commands, shortcut keys, etc a program will provide as to have a user interface that users will already have some idea how to work with based on their existing knowledge of having worked with other programs that follow CUA. Things like using Shift+Ins to paste text for example, pressing F1 would show help, F5 would refresh the currently viewed contents (if that makes sense), F10 would open the menu, Enter activate a dialog box's default action, Escape cancels of the dialog box, etc.

These are not mutually exclusive - or even related really. You can have a program that uses the VT100 to implement a CUA interface.

My point is that CUA didn't come about until after the migration to GUI's. Afterwards, no one used terminals like we do today, outside of sys-admins. So I'm aware that it's lower in the stack but my point is that the ANSI standards paved the way for any/all of this TUI goodness that the OP wants a standard for (like CUA).
CUA originated on terminals, specifically it was made to unify different approaches used across block terminals, character terminals, DOS apps, and early PC GUI apps.

It's also explicitly a Human Interface Guideline, whereas ANSI terminal standards are just interoperability instructions on how to drive a character terminal and declare nothing about how to actually use them for application UI.

Now it all makes sense. It's like design standards not implementation standards. MaterialUI over I-can-haz-ui. For some reason it didn't click.
VT100 is about HOW to write on the screen, CUA is about WHAT to write, it is on a level above (you could apply CUA while writing an app for VT100).
Which common tasks and keybindings? Can you list at least some examples?
(comment deleted)
The killer feature from magit which this seems to be missing is the ability to stage only a specific part of a hunk. When I make a bigger change and want to split it into different commits, magit is simply the best way to achieve this quickly. Other than that it looks great.
yup magit is pretty much seamless for workflows involving both squashing commits and splitting them open as well.
One can run Emacs in the terminal. What’s the use case for this?
(comment deleted)
> A rough list of so-far supported features:

> File/Hunk-level stage/unstage

One of the key features of magit is sub-hunk level stage.

If you have a diff hunk you don't want to fully commit, you can select just the lines you do want, and stage that. I use this regularly to e.g. stage most of my change but not the debug print I currently have there.