I've honestly come to the point where I have my handful of most used Magit key combinations to handle certain tasks. But I wouldn't for the life of me know how to apply those with raw git.
You could look at the magit-process buffer (hit $ in a magit buffer) to see what commands (and output) were run. That's how I look up when I have to replicate sth I did in magit in a non-magit context.
I started using it recently. It feels more like a git app in emacs, you use it in a separate buffer from your files. The shortcuts are ergonomic (single key presses, no gymnastics with modifier keys) and mnemonics are good: s(tage), c(ommit), p(ush).
Edamagit exists for VSCode and is actually quite a faithful conversion. I would love more modes like that in VSCode that just use editor buffers to get work done instead of feeling the need to create lots of inconsistent custom UI.
On the lazygit repo readme an animation is shown with a single line commit prompt/dialog. Suspicious. Is there a way to expand that one-lined thing to enter more? So I looked up "multiline commit" in the issues. Several not solved but closed issues came up and multiline commit messages seem to still not be available. This would be an instant deal breaker for me, if I were trying to use lazygit. Commit messages are not bullet points or titles. In magit I can simply type in a new buffer as much as I want to.
In lazygit you can hit lowercase 'c' to bring up that one-line commit prompt, but you can also hit capital 'C' to open the commit message in your $EDITOR and write out a detailed commit message.
Part of its greatness comes from the fact that it's in emacs. Although it might look like a GUI/TUI, magit's interface is all normal emacs buffers with all the normal navigation, selection and editing (where appropriate) features available. That's huge, but difficult to explain why if you don't use emacs.
It's frustrating for me because I believe magit is the best git interface there is. Using it increases your understanding of git and decreases your chances of error. I'd really like the rest of my team to use it instead of the CLI. But when I think about it outside of emacs, it just doesn't work.
Magit is an exceptionally well made interface to Git. Yes, it’s built on top of Emacs, and that might stop many from even looking into it. - I am glad I made a deep dive into Emacs last year, and although I stopped using it as an IDE (VS Code is just too good), I still come back to it because of Magit (and macros, general text editing and org-mode). Yes, I have an interface for Git in VS Code as well, but it‘s very rudimentary compared to Magit, and it’s limited to the narrow left bar. And to give an example: Making „micro commits“ by staging various lines of changes is super easy in Magit, but I still haven‘t found out how to select several disconnected lines for staging in VS Code.
I just found this earlier this week and this as a key ingredient of VSpaceCode (Spacemacs bindings) enabled me to finally able to switch to VS Code for Elixir & Javascript programming, which has made me so much happier.
The real value of Spacemacs is which-key and having everything already configured with semantic leader key setups. Like you can absolutely do that yourself but at that point you're implementing Spacemacs.
Actually it might require the gitlens extension. It's very well integrated and I've been using it for so long I don't know where one ends and the other begins. Regardless, if you open the diff view, the right hand side is editable and you can make selections like any other view.
VSCode with Gitlens is the best git GUI experience I've had.
I prefer most operations via git cli, but for commiting partial changes and merge conflicts, it's everything I could ask for.
Git Graph [0] already exists as a different extension from GitLens. It works quite well, although of course it would be nice if the two extensions could integrate with each other.
I just discovered that GitLens has been acquired by GitKraken. Considering that GK's entire business is "buy our premium Git GUI because the free ones suck", I have to wonder if they'll try going to intentionally wreck the extension. Fortunately it's MIT licensed.
Given I've been on/off Spacemacs / Doom for years myself, I would definitely pay for a well-packaged isolated one-click-installable Magit as a separate git client.
I recently tried out spacemacs and doom on too different new computers but I just couldn’t make them work for me. Maybe if I was coming to emacs from VIM they’d make more sense. I’d recommend that if you want to do emacs from scratch it’s probably easier to just start Witt vanilla and build up your own config. The hardest part is the muscle memory but you’re going to have that with spacemacs/doom too and then you’ve all the noise of these environments to contend with on top of that.
You can switch Spacemacs and Doom into Emacs-mode keybindings. Command key sequences become hidden behind a shortcut and modes are disabled. It relaxes the learning curve.
> You can switch Spacemacs and Doom into Emacs-mode keybindings.
Aware of this, and tried it. However much of these distributions is streamlined towards EVIL keybindindings so you don't really get the full experience. Furthermore, a lot of the Emacs keybindings have been opinionated, which again isn't bad but a little jarring.
Also the vi keybindings tend to reactivate every now and again, and often you can take a few goes to realise this as you fumble in frustration and lose your train of thought.
> It relaxes the learning curve.
Yes but you'll have a learning curve either way, and by the time you've passed it you'll know neither vim nor emacs, and you won't get to experience the joy of tailoring your own development experience nor will you have be able to make use of much of to the decades of support content that's available on the web.
As I said, it makes more sense if you've already worked with VIM and want to have the best of both worlds but even then I think you're still missing out on some of the finer experiences Emacs has to offer.
I came from VIM as well - Doom Emacs (which is just a cleaner version of Spacemacs) is learnable within a few days. Default config is almost 'good enough' for most, that's kind of the point.
Disagreed with "start with Vanilla Emacs and build your own config" though, if you just want to get started quick. Hell no, you'd be discouraged within the first 5 minutes and spend all of your time searching which ctrl-alt-meta-whatever to press to do trivial things, or copying/pasting obscure elisp snippets that you don't fully understand from stackoverflow.
> I came from VIM ... is learnable within a few days.
That was my point when I said
> if I was coming to emacs from VIM ... if you want to do emacs from scratch it’s probably easier
There is no quick start with any of these environments .. and even then it takes some detailed technical knowledge to get them up and running. They do sure look pretty! Although I found some of the default theming a little hard on the eyes for prolonged work.
> Default config is almost 'good enough'
The problem I had, was that to go beyond that it's a little trickier than what I'm used to, and there really isn't the same degree of support as what you get with more orthodox approaches. Though the community small is it is around these distributions are enthusiastic, helpful and friendly.
Like I say, the whole muscle memory thing feels quite alien at first, it soon becomes quite delightful, but not a lot more difficult to learn I think than VIM. I do like VIM, and there's many occasions where I'll use that for a quick command line based edit, and perhaps at some stage I will learn the VIM keybindings properly to the point where EVIL mode makes more sense.
I wouldn't gripe too much about the complexity of emacs, since that's where a lot of it's power lies (even if I never fully use it myself), but I wouldn't be in the habit of just copying/pasting random elisp. Usually if you've to go that much trouble it's not worth it, as somebody would have made it easier already.
could you use magit without knowing emacs? I guess you could ... but I can imagine people getting frustrated when the windows keybindings they're used to don't bring forth the expected behaviour. CUA mode exists. Would that be enough?
Is magit good enough to actually force people to learn that little bit of Emacs?
Cool to know I'm not the only one. Calc is a similarly magnificent piece of Emacs software that I don't see mentioned as much as Magit. With Org, Emacs really is the ultimate all-in-one productivity/research/dev bundle. At least in my opinion.
If GUI is your thing, I recommend giving Sublime Merge a look. I absolutely love it. I've heard that there are similarities to Magit in the terms of capabilities, e.g. staging (or reverting) by line.
What is Tig?
Tig is an ncurses-based text-mode interface for git.
It functions mainly as a Git repository browser, but
can also assist in staging changes for commit at
chunk level and act as a pager for output from
various Git commands.
> Like how easy is it to selectively stage portions of files in the git CLI?
It’s not hard (`git add -p`) unless you need line-wise selection.
The main issue in my experience is that it’s completely linear so you need perfect memory and to never make any mistakes: git shows each hunk individually and tells you to make your choice before it shows the next, no take-backs.
Magit shows the entire diff and lets you jump around, and selectively unstaging is just a “d s” away.
> I think 'git reset -p' lets you unstage a selection
That requires finishing the current staging, moving to unstaging, processing the unstaging (also a linear hunk-wise process), restarting the ataging, and remembering to skip the stuff you’d mistakenly staged.
The workflow of magit is much easier here, and the staging / unstaging integrates very well with reviewing the local or staged diff. Crafting good commits has way less friction and error recovery is much better.
Importantly, and this is why Emacs users tend to love Magit, the workflow integrates well with rest of Emacs. Your staging and diff buffers are just that - Emacs buffers. Meaning all your quality-of-life configurations and extensions are available as well.
For example, the fact that you can just jump around the buffer and stage/unstage things as you go, means you're free to use whatever you most like for that "jumping around" part. Incremental search? Sure. Ace-jump? Yes. M-x occur? If you must.
Magit on a bare-bones Emacs is extremely ergonomic on its own, but if you use and adapt Emacs for yourself, all the improvements compound on each other.
I think this largely depends on the particular person and their preferences:
- some people swear by the integration of Git into IntelliJ or other JetBrains IDEs, which is pretty good (but personally i don't really like it)
- others enjoy a Visual Studio Code plugin or two that provides a vaguely similar and enjoyable user experience
- personally, i rather like completely separate Git GUIs, like Git Cola (https://git-cola.github.io/), SourceTree (https://www.sourcetreeapp.com/) or GitKraken (https://www.gitkraken.com/)
- of course, there's also a group of people who prefer more text based approaches (Vim or Emacs plugins?)
- and there are those that enjoy using the CLI because to them it feels like the most "true" option with the least leaky abstractions
Personally, i think that you should use whatever you feel the most comfortable with and let the people around you do the same.
In my eyes, however, staging/unstaging/discarding changes to particular lines or chunks of code, as well as having visual diffs is a really useful use case for GUI solutions of any sort.
I ALWAYS use git commit -p. I can't count the number of times clion/intellij/pycharm or vscode have done something unexpected, and I often catch things that shouldn't be committed, e.g. logging statements, commented code, etc. It takes an extra minute, but it really helps the code quality. Every senior engineer I work with (developing trading system) does the same.
I always use `-p`. Its my default so its not 'more work'. Its the best way to get clean, atomic, history. It also lets me do things like mock out services or hardcode connection strings without having them accidentally exposed. I've had way too many accidental commits in the past to go back to full file add.
EDIT: also, it isnt 'line-by-line'. Its logical-chunk-by-logical-chunk. The algorithm will try to group local changes together and you need to explicitly tell it to split the chunk up if it is over eager.
I wasn't really asking how many people do line-by-line commits in general. Obviously it's useful for all the reasons you said. But it's particularly masochistic to do it via the CLI rather than through a GUI or editor.
The hunk algorithm is not very good in my experience and following the prompts to split them is just about as nice an experience as editing files with `ed`.
Have you tried using a GUI or an editor that supports staging selected lines?
Magit's more feature-rich and has better discoverability than tig, from what I can tell.
e.g. with tig, you invoke "!git commit" by pressing C from the status page.
With magit, from the status page, commit is performed by pressing cc. But, if you press only 'c', a context menu is brought up which shows the flags which can be set, and commands which can be run.
e.g. 'cc' is 'commit', but 'ca' is 'amend'.
e.g. An example of a flag might be "--force-with-lease". So, press 'P' opens the push context menu, '-f' enables the "--force-with-lease" flag, 'p' pushes to the remote. (Or just 'P-fp' quickly works, too).
tig looks like 80% of the benefits (much nicer to use than git) for 20% of the effort (not having to learn Emacs).
I love Tig for quickly visualising and browsing the Git tree. Wish it would support interactive rebase in a more elaborate way so you could maybe reorder or amend commits from the tree view itself, instead of breaking out into Git commands.
I did see the commits, but the last release was almost three years ago. That is not necessarily bad. I was just wondering whether it still works well or there are any quirks.
Even though I use magit and I think it's the best git porcelain that exists, I felt the same way before I started using it, and a little of the same way whenever I need to go find out how to do something I haven't done before.
It's just like vi, for whatever that's worth to anyone. It also has "transient", which shows you what the key sequence you've input so far will do and lets you customize it.
It's not magical. I forget commands all the time, then all I need to do is type `M-x` (to enter a command, like `Ctrl+P` in VSCode I think) and enter `magit ...` where I get auto-complete (if I do it often, I try to remember the keyboard shortcut, but that's optional).
Also, while in magit, you can type `?` to see the list of available commands from the location where you're pointing at... the commands are single-letters, so you normally do `?`, find the description you want, type `p` (push I think!?) or `c` (commit) or whatever... it's really easy and convenient.
This is one of the things that makes Emacs one of the coolest pieces of software to me. 98% of the operations it can do, are defined in functions, which you can search for easily in the M-x pane with something like Helm, and boom. Even navigation. It's a near fully self-documenting editor that I rarely need to look up help on. Never forget how to activate an action again. Remember what the action is, type it, find the matching command that is aptly-named, push enter to run it. And, with Helm for example, it even shows the keybind next to it.
Actually, what makes Magic fantastic is that it continually shows the commands and the various action keys in the gui. This provides a very accessible way of learning a very complex tool.
I love command line tools that provide hints or "command palettes". Typical CLI stuff is great for things I use at least once a week, and usually only in a couple ways. It's terrible at presenting me stuff I could be doing that I don't know about [edit: yes, I know how to use apropos, which is great but still something you have to think to go query on your own], or reminding me how to do the fifth-most-common thing I do with a tool, but that I do only 10% as often as the fourth-most-common, so I have to look it up every single time.
Git is full of that kind of thing. Tealdear and friends usually save me from digging through SO posts or manpages, so remove much of the pain, but it's still worse than having a reminder already on the screen.
(actually, some kind of automated tealdear in a second term or tmux pane, reading what I'm typing with some kind of auto-complete magic so it can show me options quickly even for longer commands, and smart enough to look up "git rebase" as "git-rebase" or whatever, would be amazing... I'll have to look into that)
Magit is such an unbelievably good piece of software. If you haven't used it, please at least take a look. It seems like "just a GUI for git", but that's missing the point — many operations suddenly become frictionless, so your entire workflow changes.
I regularly do things like "stash some of my changes, switch branch, cherry pick a commit, switch branch, do an interactive rebase reordering commits and dropping one, pop one of my stashes", and they become routine, so working with code becomes a fluent experience, rather than fighting with your tools.
I would say that Magit and structural editing using Paredit are the two most important technologies that make programming great.
You can, but it will be worth it for you to spend a little effort to learn the basic buffer, window, and cursor management keystrokes.
My 12 year old uses magit as a git interface and nothing else in emacs. That’s not a great testimonial as it was my direction to do that, but it seems to work just fine.
The areas where magit earns outsized praise is not around a basic “pull, add and commit everything, push” workflow, but rather around being selective about crafting self-consistent but single-theme revisions. That will not be as fluid for someone with no fluency in emacs keyboard navigation, but I think I’d still find it easier than using the git command line to do it. (Hard for me to say with 30 years of emacs in the rear view.)
> but rather around being selective about crafting self-consistent but single-theme revisions
Actually, I think git's got Magit beat on that. Magit might make it easier to stage specific lines, but git can stage specific parts of lines or even changes that are completely different than what's on the worktree, through the editing of diffs with `git add -p`'s `e` option.
What percentage of git users do this compared to the percentage of magit users staging line-by-line or confidently amending/cherry-picking/interactive-rebasing?
I'm somewhat convinced you can replicate that last feature (staging arbitrary / sub-line pieces of your changes) through ediff-staging (E s), but ediff is a complex tool in itself, and I don't know how to use it properly yet.
(Ediff is a 2-way / 3-way interactive diffing interface, built into Emacs, with plenty of features for surgical diffing of files, buffers, directories and whatnot.)
When your press 's', you should have a region selected, in order to stage that region - if your cursor is just sitting on a line without selecting part of it, you'll (probably) just get the whole line staged.
you can try https://github.com/jesseduffield/lazygit, i think its quite similar.
It is a TUI for git. It has made my git workflow very friction-less. Makes it very easy to cherry-pick commits, rebases, selecting chunks of files to add in atomic commits, and simplifies the resolutions of merge conflicts.
It is also integrated into lunar vim if vim is more up your alley
In my experience: yes but it I have the impression it'll remain a bit of a struggle unless you go all in and learn emacs as well.
After hearing so much good of Magit in a previous thread here I thought 'ok why not?' and installed emacs and magit. That alone wasn't a walk in the park as I never used emacs before. Maybe I did something wrong but what I remember from it is mainly 'wtf x 10 and what kind of documentation is this'. After some hours I got the hang of it, and I see why it is liked, but still it didn't make me any faster with git because I already have everything needed for my main workflows (SublimeMerge + aliases). Also felt like to get any real value from it I'd need many extra hours on the learning curve and it wasn't clear to me whether the end result would actually be better than what I do now. So I skipped on it, but again: I fully understand that if you use emacs anyway it would be crazy not to use magit.
Depends on what you mean by not liking emacs. If you prefer vim, then you can just install Evil to get similar-ish modal keyboard controls. If you are more of an IDE-person who likes controlling stuff with a mouse in VS or IntelliJ, then probably no.
I believe magit underlying ideas are good no matter what software you use, it's not an emacs only principle.
It's just keyboard oriented, text-light interaction design if you will.
invoke versionning (key 1), see what's changed, pick the parts you like (few navigations keys and 2 keys to pick/unpick), invoke commit (key 4) write and accept (key 5) (amend is key 6 if you made a mistake)
It's just fast, lean and tailored. Apparently people did it in vi too. I just wish it was the case in more places. Actually, whenever I write a vuejs thing, I try to embed keyboard as much as possible.
I used my own emacs for several years, then switched to Spacemacs. It's far easier to learn and use for most people, and also works with Vim keybindings. I'd recommend giving it a try.
> stash some of my changes, switch branch, cherry pick a commit, switch branch, do an interactive rebase reordering commits and dropping one, pop one of my stashes
> working with code becomes a fluent experience, rather than fighting with your tools
I also do this regularly, but on my terminal. I don't feel like I'm fighting the git tools. Is this a common experience?
I enjoy using git GUIs as well, especially for visualizing branches, commits and diffs. I just don't understand why the git commands seem to cause so much trouble.
After the pandemic started and I had to witness over screen share how colleagues "use" (fight) git with all sorts of GUI tools, I had to realize that no GUI can be good enough while one doesn't understand git, or, even worse, it can be contraproductive, because people using these GUIs _think_ they understand, but they don't.
I even ended up creating a (tailored)
2x90min git course...
All that said, I heard magit praised so many times, I still have some hope that it's really as good as its reputation.
(Tried fugitive, which is the vim-world's answer to magit, even learned it properly but realized I always juzt <C-z> to the terminal and do stuff with the cli)
That's a really cool article. The wording could be a lot simpler but the important part is that it does not abstract the concepts. They don't need to be abstracted because they are really simple.
Situations can become very complex, especially when someone does not know what they are doing. Developers need to learn the priciples without lies and overzealous simplifications. If you know what's going on it's a lot more doable to not end up in a super complex situation, but not a lot of people have a really good explanation of git even if they understand it very well themselves.
The underlying model of git is not too hard to understand, and is actually pretty elegant. There are a number of good explanations online, including the one you linked.
The git tool itself, though, often operates at a much higher level of abstraction. I think that's more where the reputation of being hard to learn comes from. For instance, you'd probably need to write a paragraph or two to explain what "git checkout <branch>" does in terms of the actual object store. Add to that that the CLI is poorly designed - many commands have misleading names, a given command will do completely different things depending on the flags, there's a lot of implicit / counterintuitive behavior, and so on. See https://stevelosh.com/blog/2013/04/git-koans/ for some funny examples.
1. Discoverability. It'll display the contextually relevant options and commands at most points. By using magit, you're learning the git CLI commands at the same time, including commands that you'd normally never come across without a comprehensive read of the manual or release notes.
2. Fewer keypresses. Also, extra shortcuts for some common operations.
3. The bits that CLIs aren't very good for: staging and unstaging pieces of files, viewing conflicts.
(I do still use the Git CLI a lot of the time too.)
I think (2) is why I use it, it's just much faster. It doesn't let you skip over understanding Git, it just makes you work faster.
I also think that the experiences of:
* looking into a stash and applying only selected changes from it,
* browsing all your changes and staging only some of them,
* quickly killing changes that you simply want to drop, e.g. not commit and remove from your edits
I tend to avoid using stash in that fine grained way because branches are cheap in git, and you get a rich set of operations using a local branch to stack up unorganized code changes. Rely on stash on only very quick setting aside of work then returning to it. If I stash and find it needs to live longer than that - I’ll stuff it into a named branch.
Re: 3 ... I find that the CLI ("git add -p") works here when the scale of the changes I've already carried out is fairly small and there are not too many orthogonal changes in the file tree that I want/need to commit separately. If that happens, it's off to magit I go.
I'm usually a pro-GUI person but I've always found git GUIs to be confusing/trying to paper over the model in a way that made me not like them. Though I don't mind what IntelliJ has. Maybe I need to give this magit tool a try as well.
Magit is absolutely fantastic and it reduces friction, discoverability and joy. rebasing is easy. commiting is easy. staging is easy. discovering is easy. everything is easy. it's incredibly powerful and also incredibly easy to use. it's simply the best software i've seen written in a long time.
sounds like hyperbole but it's not.
edit: magit is like if you spent months crafting a bunch of aliases for the command line and then made a nice little menu of all of them and committed that to memory but also has it as a popup. and even then magit is an order of magnitude better... handily so.
What I dislike with git terminal UI is that commands reflect the innards of git, not what the user wants to do. It also forces a deeper understanding of the innards for basic commands than ought to be necessary.
Examples where undoing an operation looks totally different to doing it:
- To stage a change you `add` it, to unstage you `reset HEAD`
- To commit you `commit`, to undo a commit you `reset --hard HEAD^`
The last example is also where you get pointed to an unsafe command for a fairly benign operation. Uncommitting is not particularly dangerous, but anything with `--hard` ought to give people a pause for thought. If you mistype it and nuke more than the last commit, that's also a bit bad - and fairly easily done.
Some other examples include shenanigans around pushing and pulling remote branches. After 10 years of using git, I still need to google it each time.
I think these commands are an accurate and reasonable representation of its inner state, but IMHO users should at least have the option of being somewhat isolated from it. Git is not a tool for algebraic manipulations on directed graphs, it is a version control software.
It has to be said, to git's credit, that although the commands are confusing to some (myself included), the tool works very well. I wanted to like mercurial more, but ended up going back to git, as much as I dislike the UI.
But this in fact reinforces my overall point. I don't want to be messing with `reset`, hard or soft. What is `reset`? [I now know because I had to learn, but I'd really rather not].
What I want is `uncommit`, or something like that.
That’s a valid point. I think there’s a near consensus, even among people who admire Git and use it constantly (like me, although I’m no expert), that the porcelain commands are confusing in some respects.
On the plus side, Git’s man pages are (sometimes) useful and pretty complete. In this case, if you type `man git-commit` you’ll get a thorough rundown of all the options and it will be clear which one you should use to get what you want.
EDIT: Also, since there are three arenas to keep track of, the file tree, the index, and the commit history, even if there were an `uncommit` command it would need all the flags that `reset` accepts. So it would just be `reset` renamed, which you can do yourself. But maybe some of the `reset` options should be broken out into separate commands.
This creates a new commit that reverses the changes of a past commit. That’s different from undoing your last commit, as in, you made a commit but then changed your mind, and want, say to make some more changes before you commit. (Explained in man git-revert.)
> Git history is intended to be immutable when working with others.
That's another pet peeve (though maybe less git's fault): immutable, yes, but then rebase is pushed quite liberally. Arguably not by git itself, but by many online learning resources.
It's convenient, and mostly works, but then occasionally really stings you.
...yet undoing the last commit, arguably the least aggressive of history-rewriting commands, remains awkward.
How is "git reset HEAD~" "awkward"? It's not obviously named, but as was noted above, if there was git-uncommit, it would need every option that git-reset has, and so it would just be an alias, without the final argument.
"History is immutable" is generally accepted as describing the contents of commits, not their id's or relative ordering.
It's also very wise to make sure you disallow force pushing to master/main/production. If you force push to a topic branch, it's usually ok. If you accidentally overwrite someone's changes, it's because you are working together and you can communicate that you messed up and for them to `pull --rebase` or however you want to resolve it. Usually that is. There's always room for disaster :)
Oh right. I always neglect to do that mostly out of laziness of typing it out on the command line. It's funny, though, I maintain a branch plugin for vim (it's a fugitive extension) and I recently accepted a PR to switch `--force` to `--force-with-lease` yet I still don't do it. I need to start doing it!
> Usually that is. There's always room for disaster :)
For me, this is where the problem with got lies. I use so many of it's commands infrequently enough that I don't know where the weird disastrous edge cases are, where I should use.
I think git would greatly benefit from a topical man page; a list of common and uncommon situations that shows the recommended commands for solving them, and explains what those commands do. I know that hundreds of random "guides" exist, but are they outdated, are they cannon, do they have bugs? When your UI is esoteric, situational documentation is really important.
Ya, the git UI is not great. It has improved a ton over the years but still not great. Have you ever seen Git Koans? It's good for a laugh. https://stevelosh.com/blog/2013/04/git-koans/
If git at least had good man pages. The man-page's description is "Given one or more existing commits, revert the changes that the related patches introduce, and record some new commits that record them." [1] I have a hard time parsing that to mean what it's supposed to mean.
It contains a note that's much better at explaining what git revert does, then goes on to explain alternatives for other things you might want to do, but doesn't mention how to undo a commit without creating a reverting commit.
“ I have a hard time parsing that to mean what it's supposed to mean.”
Can’t disagree. That part could certainly be written better. I’m not saying I would want to learn Git from the man pages, but they’re pretty good in general after learning it elsewhere.
They are decent for reference, and some are genuinely great (like git-everyday [1] or git rebase [2]). But just as often as they are helpful they just leave me scratching my head, either because they are too deep in git-lingo or because they forget to clarify some crucial details
- git revert {rev} to nuke changes and go back to how the world was
- git uncommit to return to the state literally before git commit
- git unstage to unstage a file
The latter arguably should go with git stage but it’s a bit late for that. NB git add and git rm are totally not inverse operations...
So then I can uncommit, and unstage if need be. Reverting is for discarding changes, and should come with an interactive confirmation prompt and other safety and hygiene messages.
> git uncommit to return to the state literally before git commit
This is ambiguous because there are many such states.
1. Clean working tree, before you began hacking on the code.
2. Modified working tree.
3.1. Modified working tree with staged changes.
3.2. Clean working tree with staged changes.
It's impossible to know which state you want to go back to without telling git. That's what hard, mixed and soft resets do: they bring you back to states 1, 2 and 3.2, respectively.
The default is a mixed reset. I suppose state 2 is what most people want when they try to undo a git commit. So it already does the right thing by default, no?
The only remaining problem is the git reset argument. An undo command will always reset to the previous commit, there should be no need for arguments. Stuff like HEAD^ or HEAD~1 is quite obscure to the uninitiated. We could certainly have a git undo command that runs git reset HEAD^ and allows hard and soft resets. Not sure why it doesn't already exist. Has anyone ever attempted to get that merged into mainline git?
The default for `git reset`, which is `--mixed`, may do what you want. The difference between `--mixed` and `--soft` is that the former resets the index as well as moving the HEAD pointer; the latter only moves the HEAD, so if you’ve `git add`ed any changes, they will remain staged.
Yeah, keeping track of Git’s three areas (files, staged changes, repository) can get confusing. After some thought I think my advice to you to use `git reset --soft` would be better as just `git reset`, because that’s a neater “starting over”: it’s more of an “undo” of the last commit action, I guess. I often find myself reaching for `git reset --hard` after screwing up and not feeling like tracking down how I broke things.
Reset is a powerful command that happens to work for the “uncommit” use case. I use reset for a completely different use case: my CI system watches a specific branch for changes and when they occur builds it with a specific configuration. If I reset-push a branch, I get a build of that branch with that configuration.
Yeah, git is certainly a low level tool. That's actually what I like most about it. There's a few fundamental concepts I get to manipulate directly with git commands. I like dealing with innards like this because I can form a mental model of the tool. High level tools are a lot harder to understand.
I think the problem with add, commit and reset is they aren't low level enough. The reset command in particular is juggling several concepts at once: HEAD, the index and the working tree. The add and commit commands work with fewer concepts: working tree to index and index to commit, respectively.
I too google the commands I don't use often. There's no shame in that.
I probably pushed and pulled O(100) remote branches over the past decade (jeepers I'm getting old), so roughly once a month. It's not that rare, yet I still haven't memorised them, because I find them so unintuitive.
Once a month is close to my usage and it's often enough to remember things in principle but not often enough to remember the d#$%#$%^#$n syntax with all its obscure details.
Depends on the result. I do interactive rebases extremely often, I don't have to look up how it works.
Sometimes I have to use some command I'm not familiar with. Sometimes familiar commands gain new options. It's perfectly okay to use some reference for that. Also, "more time" is like 1 minute.
Yes, except... again, this is fighting fire with fire.
If you don’t know git internals, mistype a non-obvious command and lose a bunch of commits, then “look in the reflog” advice is frankly adding insult to injury.
> It's really hard to lose changes once they've been committed.
I've still managed to do it (or maybe I used git rm to delete some files that weren't committed?) so let me give one more shout out to 'git fsck' which saved me here.
The reflog is awesome! It keeps pointers to commits that have been dropped, rewritten by rebases, stuff like that.
Git is garbage collected, even if a commit is dropped from a branch it won't simply disappear immediately afterwards. The object is still in the git repository and it can still be reached, most easily through the reflog. Only when garbage collection is performed will any unreachable commits be deleted.
"- To commit you `commit`, to undo a commit you `reset --hard HEAD^`"
You're not meant to delete commits like that. Git encourages you to stop "lying about the past", and you will run into a fair amount of trouble if you try to do so with shared history. You don't remove a commit "backwards" and change history; you add a new commit that undoes the previous one (git revert)
Couldn't disagree more. To me, one of the massive advantages of Git over other VCS tools is the support and completeness of its ability to edit time. You are the editor not just of the content under control, but over its branched evolution. Accepting this and working with time gets you to a next level of control.
The first step in this process is really internalizing the tree of commits, and seeing branches not as lines of development as much as simple pointers on that tree. In many VCS systems, branching is a big deal. In Git, a branch is just a smart tag that is automatically updated by HEAD. Users new to Git need to get comfortable creating branches at a whim as the tree grows.
The next step is getting comfortable with editing the tree itself. Primarily, I recommend using interactive rebasing liberally. This has multiple positive side effects:
1. It causes the author to think at a higher-level of the primary artifact they're constructing — the tree of incremental changes.
2. Authors begin to think about the repository as more than a dumb file backup system, but instead as a history with true utility, and so begin to construct "stories" in that evolution that are instructive and useful to future readers of that history.
3. It takes the author out of the flow of time, and encourages them to think about ways to change the past (within limits, of course) so that the constructed history is improved.
All of this, of course, with the caveat that shared history changes must be coordinated (and frequently avoided). You can get very far thinking this way just about your un-pushed topic branch.
There's a very real philosophical difference between those who see VCS as a secure audit trail (where changing history is "lying about the past"), and those who see a repository as a whole constructed artifact of intrinsic value, wholly editable as its contents. In this latter view, editing a line of source isn't "lying" about that line's contents, and neither is editing time.
Interactively rebasing your local changes instead of sharing a hodgepodge of brain vomit is great, but don't go around rebasing history that's already out there between a team of developers unless you have a really, really good reason to.
I did specify that rewriting shared history is going to cause you trouble (unless you really know your way around things), but apparently it wasn't clear enough
After trying a couple of times, I haven't been able to get used to magit, and I gave up. I'm very used to the git command line interface, and magit is just too different from that. For instance, it seems to assume I want to operate only on a file, whereas most of the time I want to operate on the whole repository. I have no idea why someone would want to work like that.
I found it was taking a lot of extra research to get it to do what I wanted, and I was completely confused by its choice of default behaviours, so I gave up trying. I would welcome an interactive tool that is more oriented around the way the command line tooling works, but magit does not seem to be it.
I do have magit installed however, because I really like how it controls emacs buffers while using interactive rebase. But I never use the rest of it. I have no interest in trying to memorize which hotkey does what, and how to bend yet a new interface to my will (that apparently disagrees with my preferred default behaviour), when I already know the git command line.
If you start from the magit status buffer, most things operate on the repo, except file-specific commands like staging, unstaging, etc. For those, if you run the command with your cursor on the heading, rather than with it on a file (e.g. on the “unstaged files” heading rather than on a particular file), it will ask for confirmation and apply the operation to all of the files.
More generally, magit applies operations on whatever the cursor is on, when it makes sense to do so. This is very convenient e.g. for staging parts of a change at different granularities: I can stage everything, then unstage a file, then stage a hunk within that file. It only takes a few keypresses, compared to a long set of commands followed by dredging through add -pi.
There is nothing wrong with using git commands in the terminal.
There is also nothing wrong with copying your entire tree to a different directory, diffing, applying patches by hand, and keeping track of what goes where.
Those are different levels of automation for the same fundamental task, but they are all legitimate solutions to the same problem, although you might end up spending more or less time to perform the same fundamental task, depending on the level of automation.
> There is also nothing wrong with copying your entire tree to a different directory, diffing, applying patches by hand, and keeping track of what goes where.
What? There is plenty wrong with that. I've worked with people who did that. There are lots of problems with this approach. It's extremely hard to work with and it only gets harder the more people are involved. At least in git the commits have unique identifiers, everything is hashed and checksummed automatically, branches are properly tracked, etc.
I've even worked with non-programmers whose version control was emailing each other files named like:
Presentation final final REALLY FINAL (2) (3).ppt
It was a hell unlike anything else I had ever experienced before.
You probably don’t feel like you’re fighting your front door when you walk out of your house or apartment also right?
All that means is that git tools, and your front door, work well once you have mastered them. The ease of use and discoverability of tools over the life of their learning curve is what determines if they are a Norman door.
For lots of people, using a Unix command line or Git for the first time feels like a Norman door. This is why other interfaces exist (like guis) for the same tools.
> I also do this regularly, but on my terminal. I don't feel like I'm fighting the git tools. Is this a common experience?
My big hang-up with interactive rebases is that I do them just infrequently enough that what exactly a set of choices will yield—what's going in the commit message, et c.—is something I have to sit there and reason about for a really long (by the standards of something that really is not that complicated an operation) time. I can also never keep it straight when editing messages in-line will have an effect, and when it'll be ignored (in some commands it is, IIRC, in others not? I can never remember, but either way, why the hell let me edit it if it won't do anything?)
What I could really use is a live preview of what the effects of my current choices will be.
I prefer to do my interactive rebases in steps, instead of all at once.
If I want to rebase changes onto a different commit, re-order them and squash some of it, I'll rebase as-is first, then do another rebase and reorder everything so that squashes are next to each other (and yes, sometimes this means unnecessary conflict resolutions), then a final rebase to squash. I'll edit messages last.
Interactive rebases are my favorite git feature. I get to pick, drop, reorder, reword, fixup, squash, split and of course rebase commits. Pretty much everything I need to create a nice history before pushing.
I like having both. I use fugitive in vim which is great for partial staging, blaming, and committing (and status). Almost everything else I do on the command line. I will also commit from the command if I already happen to be there. The one thing fugitive is indispensable for is looking at a file on a different branch right in the editor.
> I don't feel like I'm fighting the git tools. Is this a common experience?
Yes. Today I spent way too much time explaining to a coworker that what he was complaining “should be easy to do but seems impossible” was actually quite simple, only to spend ages explaining how git works, why he wasn’t understanding the paradigm. And after all that help what he needed to do was simply to “git checkout feature-A && git merge master” we didn’t even touch on rebasing, and it’s not like he hasn’t used git before, he had at least half a decades worth of experience working with codebases managed in git.
And this is far from the first time that I’ve had to help out people with something that seems extremely straight forward to me and others who have git under our skin, but is overly complex and difficult to people who might not be experts but have worked with git for several years in a state of “minimal viable knowledge”.
Git has the same problem as it’s creator, it is arrogant, and has for way to long tried to explain the fact that new users find it difficult with “well they are just dumb” instead of accepting that it needs to make its user experience and interface more intuitive. Some of these changes are finally happening now, so I no longer have to explain why “git checkout” is used for seven completely unrelated things, but there are still tons of cases where the “straight forward way” to do something is only accessible to people who have spend way too much time doing deep dives with git and fully explored all the edge cases just for the fun of it.
It doesn’t help at all that googling issues is swamped with advice of “just force it” or “delete the repo and clone it again” which can cause permanent damage to the codebase, for a tool that is at its center suppose to avoid permanent damage to your codebase. No matter how stuck up some blinded advocates of the “git is and has always been perfect”-camp you are, everyone should understand that needing to give advice like “and if you have an issue don’t Google it, go see me or another git expert first to avoid loosing code history” is at its core spotlighting fundamental issues in the tool interface.
“minimal viable knowledge" describes my git knowledge. I simple don't have time to become a git expert. After all git is only a source control tool, there are way more important things to deal with that impact our customers.
> I just don’t think there is much value in learning more. It’s just a version control system.
I think it's not a matter of "just" a version control system; it's vital enough to (most of) our jobs that being more than just "minimally viable" good at it is an integral part of being reasonably competent.
But who am I to talk; at work, I almost exclusively use Informatica's built-in "version control system", which IMO... isn't much of one; actually, hardly is one in the first place. Getting to use git (or similar) again is what Idream of. Then again, maybe that just means I'm only "minimally viable" with Informatica's system. :-)
(All out of Spätzle, have to wait for next "Alpenfest" week at Lidl. :-( )
I was like you for a really long time. Then, I watched someone do stuff in Magit that took longer or I struggled with to get perfect in the terminal. Took a few weeks to get comfortable, but once I did, it was really nice.
"I just don't understand why the git commands seem to cause so much trouble."
To me the git command line is one of the tools that are great if you use them often. But if you use it less often it's really hard to remember the correct syntax especially since it's really easy to mess things up. (If know WPF, the binding syntax is in the same category. Really powerful but if you take two months break you struggle with the syntax). It really bugs me in git when normal things need 3 or more parameters and if you forget one of them you mess things up.
Years ago I worked with mercurial for a while and I thought the commands were much cleaner and easier to remember.
If you know git cli very well, most of the stuff are straight forward. Most people struggle with git if they have not spent the time to understand how it works.
But there is one thing I believe is still not-very-smooth in the git cli: splitting hunks.
if I do interactive add in git, and I get small hunk that adds a line, deletes a line, adds another line, and deletes a line, then if I want to include only the addition of the second line, it is pretty annoying in git cli. In magit, it is basically selecting the line and pressing "s".
I don't feel like I am either - I think some people are not fans of CLI. Full disclosure: I also don't "get it" when people say they can't use tar without looking up the help/man pages.
I get by with less than 10 git commands - in rough order of decreasing frequency: pull, commit, add/rm, push, stash, checkout, merge, and more rarely bisect, revert and reset.
> I also do this regularly, but on my terminal. I don't feel like I'm fighting the git tools. Is this a common experience?
Trying to stash some of the changes is pretty annoying, yes. New files don't want to cooperate with stashing, and there's no way to stash just staged things like making a commit; you have to use -p.
> I would say that Magit and structural editing using Paredit are the two most important technologies that make programming great.
That's interesting because those are two tools I've tried to adopt multiple times, but never have managed to do.
Paredit is at least partly due to my long use of vi (and almost as long use of vim) keybindings; I use evil-mode, and bind << and >> to the appropriate adjust-parens functions for strucutural editing.
Magit is due to me having used git for so long that it takes me at least 5-10x as long to do something with magit as with the git terminal, and I'm just not at a point in my life where I desire to fight with my VCS when there is another option.
I suppose I'm just stuck in local maxima with regards to those two things, but I'd say I'm fast enough.
Magit should be studied in computer classes. I'm from the eclipse j2ee college era. They tried heavy OO guis, none matched the ergonomics of magit. I'm still surprised to this day how lean and translucent magit feels.
People should try this kind of thinking instead of big engineering principles that only slow the machine and the user down.
For the sake of discussion, can we get some contrarian views?
I'm using magit, along with tig, plain git and sometimes (!) even plain "vc", depending on context. I'm in the camp that thinks it's ok and it's pretty comfortable to use within emacs, but I don't see the earth shattering praise I see every time it's mentioned here.
Tig for example is so much faster for history and blame perusal that I find it faster to keep it open in another terminal and just switch to it.
Magit is unfortunately so slow on Windows that it's unusable. This is a real shame, because the UI is fantastic. I think a better architecture would use libgit2 calls rather than launching multiple git processes for every single magit operation.
Is the launching of processes on Windows so much slower than on Unix-type OSes that it would cause it to be "so slow" for that reason?
Maybe the reason is another? Personally, I once had Magit act real slow at times because git-annex had added some git hook for something that I didn't need. Just removing that hook improved performance massively. Perhaps something similar is happening.
Also, I'm not sure Emacs Lisp can interface directly with C libraries, so using libgit2 might not be an option.
Unfortunately, it's pretty slow on macOS, as well. I love Magit, but there are times when I feel like it's hindering me more than helping due to the performance.
That, and I often have multiple projects open at once. There's a note in the Magit manual about this and how it affects performance, but unfortunately, the workaround means that buffers don't get refreshed and you might see stale information unless you perform a manual refresh.
I'm pretty sure it's the main reason. Look how many times Magit shells out to git to render the status buffer, too many to count: https://github.com/magit/magit/issues/1327
In a perfect world, Emacs would link to libgit2 and Magit would be adapted and folded into the core distribution.
I just called the status buffer from magit on a repo. It was 23 calls to git, mostly for rev-parse. The status buffer appeared instantaneously on a decade-old laptop.
Whatever is causing the slowness you're seeing, I don't think it's just because of the number of calls. It's probably the slowness of one or two specific commands, perhaps due to repo size.
Are you testing on Windows though? I am specifically talking about Windows being the (biggest) problem with this architecture. It is very expensive to create new processes on Windows versus Unix (threads are cheaper on Windows though).
Another commenter said that they also experienced slowdowns on macOS, so I thought the OS actually didn't matter much on this, but based on disgruntledphd2's comment, I guess it does.
Magit is not particularly fast on *nix either. Most of the UI operates on buffers which are prepared infrequently, so the latency doesn't have significant impact. This is a very good UI design for magit itself, since staying within emacs provides bigger benefits in most cases.
However, my own cited example about browsing history and blames is one case where I cannot just stomach the subpar efficiency. Tig also runs git as a subprocess, but every view is truly incremental and you can scroll through any buffer in any view and there's absolutely zero delay. Night and day even when comparing emacs with JIT.
Like for magit, tig has one keystroke shortcuts that make sense (which IMHO is pretty common on good TUI programs) and can perform many git operations directly from the spot you're looking at.
I also consider the visual space usage in tig to be much more efficient as well. Especially the blame view, which I find still wasteful in all modes compared to tig's. I frequently use a customized vc-annotate instead.
Magit hooks also considerably slow down operations on remote files, which can be quite annoying if you don't actively need to use git while editing.
Don't get me wrong - I like magit. But like org-mode, I don't get the glorification it gets.
I use emacs and git, and never got on with magit. Not entirely sure why, but here's a braindump:
- I generally dislike layers on layers; while I seriously hate the git UI, I'd rather learn that, as it's a more portable skill, than learn another UI, that relies on emacs and a package installed. First thing I do on e.g. a new cloud instance is clone a bunch of stuff, and often work on an under-setup machine for a while. For similar reasons, I don't use shells like Fish, which, nice as they may be, funnel me into something totally incompatible with good old sh. Bash and zsh, as far as I use them, are compatible.
- I work in tmux, and emacs in terminal, the overhead of switching to a terminal and typing some git stuff is tiny.
- I tried magit and just didn't get it. I couldn't couldn't find a happy path where I thought, "ah yes this is niice".
> - I tried magit and just didn't get it. I couldn't couldn't find a happy path where I thought, "ah yes this is niice".
I mostly use plain git instead of Magit, for more or less the same reason, although I like git's UI.
I did find a happy path, though. Magit's blame interface is very nice to recursively call git-blame and navigate history of pieces of code. I ended up making a CLI program to improve git blame[1] so that I didn't end up switching to Magit just for that, but doing git-blame from Magit is still better.
I'm not a terminal maximalist, but most git actions are easy to perform from the terminal. Switching to a terminal and typing the right git command has little overhead, and it's a universal way of doing things.
> I generally dislike layers on layers; while I seriously hate the git UI, I'd rather learn that
I'm surprised to hear this. Magit is a very thin layer on top of git. Not thin in the technical sense, but in UI/UX sense. Keybindings map almost one to one with git CLI. Arguments to the git CLI are explicitly stated. Executed git command is reported. I learned git better by using Magit.
> I'd rather learn that, as it's a more portable skill, than learn another UI, that relies on emacs and a package installed
FWIW, most Magit commands have 1:1 correspondence with git commands; when I'm worried I'm doing something with Magit that I wouldn't be able to replicate with CLI, I just press '$' to pop up the "process buffer", i.e. the buffer containing actual git commands being executed, along with their output. Conversely, I still read git documentation to figure out more advanced Magit workflows.
My way of looking at it is, Magit is just an ergonomics layer on top of git - it doesn't introduce new abstractions, it just lets you do stuff in a more efficient and interactive way. The love comes from that efficiency - the improvement is big enough to make a qualitative difference and affect the way I interact with git.
(And, of course, you can just press !! and type in whatever git CLI command you want, to run in context of your repository.)
> the overhead of switching to a terminal and typing some git stuff is tiny.
Switching cost is low, but typing cost is much greater.
Of course, everyone has their own preferences. I personally swear by Magit, and I'd love to have more command line tools be integrated with equivalent interface. Magit's UX paradigm isn't a total replacement for all CLI - but it's perfect for tools you repetitively invoke with different parameters to sculpt something.
> Switching cost is low, but typing cost is much greater.
That typing cost is why I use a GUI. While many times I can just enter `git add -u` into the terminal, there's still plenty of times where I want to be selective about what goes into the commit. If a simple glob pattern can't do it, then I'm going to reach for the GUI where I can just click on all the things I want to add to the commit in far less time than it would have taken to type all of the file names.
The GUIs also keep me immediately informed on the state of my repo. On the terminal, I'll be running `git status` a lot, just to be sure the state I think the repository in in and the actual state match up.
Yup. But then, clicking time (or rather, navigating your mouse) is also slow. Where Magit shines is in being a GUI (a TUI), so you're always informed on the state of the repo, but it's also fully keyboard operated, so you don't have to click on things.
The popup-based paradigm for keyboard operation helps with discoverability - first few times around, you'll be going slow to learn what key does what, but after that, you'll be issuing most commands from memory.
I remember when magit went from 1.x to 2.0, a couple of common commands changed keybinds and it was extremely painful to change the habits as they were commands I typed hundreds of times per day. Still it didn't take long to adapt.
I say "click" but I really mean select. Mouse or keyboard doesn't matter to me. Something being a GUI instead of a TUI doesn't mean it can't be designed to be entirely keyboard driven (and hell that goes the other way too: since a TUI can get mouse events, you could write one that isn't fully keyboard driven).
The key point I was trying to make is that an interface that minimizes the amount you need to type out and that gives you instant feedback to your actions is a superior experience for working with Git in many cases. I say this as someone who uses Git from the command line a ton (to the point where I've added some custom command scripts) but then when I need to do anything complex or browse the logs and diffs I'll enter `gitex` to bring up the Git Extensions GUI.
Magit can do everything IJ can, but in IJ, I can find how to do things more easily and it just feels easier to do things, probably because it's much more GUI than text compared to Magit. For example, difficult merges are extremely easy in IntelliJ, I can edit code in the diff view itself while I resolve conflicts... in Magit it requires getting used to the different diff views, something I am still trying to figure out, but it seems trickier to do "in-place" changes in the code.
That said: I probably only prefer IJ because I've been using it much longer than I have used Magit... and the difference for me is very small, so I suspect the more I use Magit, the more the gap will close and I may eventually like it even more than IJ.
IntelliJ GIT ui/ux is so completely frictionless it's magical at times. The only downside is that it makes incredibly complex operations trivial that I never learned git from the cli beyond the very basics.
Really? I tried it yesterday from within Rider and I gave up on it because I couldn't even figure out how to push or pull. Best I could find was fetch.
Not the biggest deal since neither of those commands require interacting with the output which makes them equally easy to run from the terminal, but it's strange that they're not available in an immediately obvious place.
You can customize the menu (and I do) to add a Git menu sub panel (for lack of a better word) that has an up and down arrow for push and pull.
In the lower right, there's the vcs "where you're at" that shows the current branch. From there you can see the status of your branch compared to others (if you need to fetch them), or you can update branches (even those you're not currently on) along with branch specific operations including push. You can access the same in the git panel with right clicking on branches in the log.
At any time, you can double tap shift to bring up the "search everything" window. Within that, if you type "git push", it will display that action along with the menu that action is in and any key shortcuts that are bound to it.
Oh wow I didn't know that search everything in Jetbrains products included the menus and not just the contents of the project. That's handy to know. I've been a fan of Ctrl-Shift-P in Sublime Text, so it's always good to see similar features in other software.
I've used it for the "where is that show whitespace menu setting? meh... shift shift whitespace. Change setting."
Also, glance under the "Help" menu - there's a productivity guide. That shows you a whole bunch of features (and how often they're used) and how to use them.
Others mentioned the shortcuts, but there's also obvious buttons in the toolbar with a green up-arrow for commit+push (the button for Commit has an option to also Push) and a blue down-arrow for pull.
IntelliJ's git interface is basically the only way I can use git, or at the very least pull off anything other than the most standard tasks.
Its UI for resolving merge conflicts is so intuitive and powerful. You get 3 panels: local changes on the left, remote changes on the right, and merged in the middle. It's got colored highlighting going across from each of the side to the middle, showing where the changes want to go to, and you click arrows to accept/dismiss left or right, and sometimes it'll even have a suggestion for a way to take both of the changes (indicated by a magic wand). And you can also just type into the center editor if you want to not use either side, and manually rewrite the resolved change yourself, whether that be copy-pasting from each side or whatever you want to do.
It's saved me so many times, it's practically worth the cost of the entire IDE on its own.
I get the same impression using org mode vs hearing people talk about it. It's great! but the way it's talked about makes you think it will change your life and finally stop you being a lazy procrastinating fool.
It's very cool and flexible and doesn't tie you in to any big tech provider (yay!), but it's just an outliner at the end of the day.
I like org mode, I use it every single day, and I'd agree most of the time. 9/10 I'm using it as a glorified markdown editor, but on that 1/10 occasion where I get to do something really cool is where it feels magical.
I'm not going to post anything "contrarian," so to speak, because this really does seem to be an excellent tool.
I will say that I won't be using it, as I use GUI tools, with a far smaller "power" level, and use command-line Git for the few times I need anything fancy.
I'm not familiar with tig. Is it convenient for staging chunks of code or even individual lines? Interactive rebase including re-splitting commits? Cherry-picking stuff?
While working on kernel I sometimes get "looks nice, but can you reorder and re-split this 15-patches series in completely different way?" and magit is a big time-saver for that. It wasn't as useful on my previous jobs where 1k-lines commits with message like "Implement feature X" were the norm, though.
I'm using Visual Studio Code for basic git functionality and switch to Visual Studio proper when I have to deal with gnarly merges. Merge UX is fantastic in VS.
My contrarian view: I pronounce it maggot. I think Mag-it sounds weird.
That said, I’ve financially backed Magits development (Kickstarter iirc) and I use it almost everyday, but I don’t do merges with it. I’ve had some large merges go really slow thru Magit. So I always do my merges in the terminal using the plain git CLI.
I picked up Sublime Text + Merge a few months ago (I wanted Sublime Text and figured I'd try out Merge since the bundle was cheaper), and it turns out I use Sublime Merge way more. (Sublime Text is fine but for my workflow it has a bunch of gaps with Visual Studio that I haven't been able to fill).
Sublime Merge and vscode + git plugins are pretty close to each other but Sublime Merge does everything I need with less fuss. vscode just has some rough edges due to it's swiss-army knife approach that Sublime Merge doesn't.
I can't imagine (haven't tried it so I'm just speculating here) that Magit functions very comfortably on something like a deep clone of the Linux repo, but I think there would be very few monolithic projects most of us would encounter with that kind of lengthy history in our day-to-day work. Maybe some Googlers could weigh in on how their large repos are handled by Magit?
I was pretty skeptical about magit at first because I know all the basic git commands for my daily workflows by heart and I don't find them to be very difficult or slow to use. But since I am also an Emacs user and everybody kept telling me to try it out I finally forced myself to use it. And I must say it is very easy to pickup and use productively. It is way better than most of the git integration features you get with your typical IDE (like VScode for example) because magit supports most git workflows pretty seamlessly. It integrates itself nicely in Emacs' keyboard driven UI. So now I don't need to drop to a shell anymore to interact with git.
But does it make me much more productive? I don't know.
While developing typically I add some debug code mangled with the actual stuff. So when I am ready to commit I've got to remove that first. I had done this manually in the editor before, now from within magit I can just select the lines I'd like to stage and press "s". Then proceed to commit pressing "c". Finally, by just selecting the remaining lines and hitting "k" ("kill") I get rid of all debug code. That's pretty nice and I will never ever forget to remove debug code again. Similarly, you can manage your git stash with a couple of key strokes.
Branching and merging works well, too. But I don't think magit makes it much easier as you still need to type in branch names. Autocompletion is supported, but git provides this as well.
Merge collisions are still a pain. And for more complicated tasks like interactive rebases, reflog rescues or bisecting I still keep dropping to the shell. I actually like the expliciteness, here, because it prevents me to stupid things in dangerous maneuvers. And "git help" is always there to remind me on all gazillion command line arguments.
I find magit very nice for interactive rebases. The ability to instant fixup older commit is also nice.
But yes, I do drop to the shell for some actions when I know exactly the sequence of git commands that I need to execute. Also somehow I often use the shell to switch branches, some habits are hard to change.
> I was pretty skeptical about magit at first because I know all the basic git commands for my daily workflows by heart and I don't find them to be very difficult or slow to use
Same here. I've found completing-read for branch names to be one of the biggest draws for Magit, personally. I can tab-complete them in my shell, but it's much slower and less reliable.
This will open the repository under the current path in a maximized magit window.
The only downside I have for now about magit is when using `pre-commit` it can run for long sometimes, so it would be nice to see the progress/output of pre-commit while waiting for the commmit message buffer to appear. If you know a way I'm all ears.
Fugitive is amazing. I was once pair programming with someone, noticed a weird line in the code, used the in-line git blame, then open that whole commit, and could analyse all the changes right there in neovim.
Compared to opening up Github, or stashing and checking out via git manually, it was so much faster.
I'm surprised that I had to scroll this far down to find mention of fugitive. I haven't ever used magit but I use fugitive every single day and absolutely love it.
I will say it right away: Magit is one of the best software I've ever used. Please support it regularly. Scroll to the bottom of the page to learn how to support.
I use git from the command line, so this looked like a tool i would use.
I was able to install it with apt, but i could not find any information on how to run it. Manual says "C-x g" [1], which obviously does nothing in bash.
And I have no idea how to use emacs.
Is there any helpful user manual? Should i give up on magit?
Emacs comes with extensive documentation. "C-h t" opens an interactive tutorial that teaches the basics, "C-h r" opens the manual. "C-h i" opens the Texinfo browser that gives you access to even more documentation, including manuals for Emacs Lisp and Magit (if installed).
The learning curve is fairly steep in the beginning, but after ~15 years, I feel that the initial effort has paid off a lot. Not everyone likes emacs, and that's okay. But I do think it is worth giving it a try and seeing for yourself.
(As for the whole vi-vs-emacs debate, I have used both over time, and I do use vi quite regularly for quickly editing some config file. There are packages for emacs, like evil-mode, that emulate vi's key bindings and behavior, but I have not tried any of them.)
Initially, I switched from fossil to git because I had to use it at work. After finding out about magit, I have never looked back. For me, magit made git not just painless but actually fun to use.
I love magit, I’ve been using it for a year, which is as long as I’ve been using Emacs. But can someone please tell me how to pronounce magit? If I try to make it sound like magic, I pronounce it the same way as maggot, which seems wrong. If I put the emphasis on the second syllable so that it’s emphasizing git, that also feels weird.
356 comments
[ 2.8 ms ] story [ 225 ms ] threadI also like git-timemachine for stepping a file forwards/backwards through commits (that's not part of magit, I just think it's neat)
So yea, people are building it out of emacs!
Do you have any specific workflows that you prefer one over the other?
It's frustrating for me because I believe magit is the best git interface there is. Using it increases your understanding of git and decreases your chances of error. I'd really like the rest of my team to use it instead of the CLI. But when I think about it outside of emacs, it just doesn't work.
Ok, soft G might be the best choice.
Hopefully that's just because VSCode didn't allow arbitrary widgets until recently. Presumably they're working on it.
[0] https://marketplace.visualstudio.com/items?itemName=mhutchie...
In the Source Control window, select your file then in the right panel:
- Select the first range of lines
- Alt + select the second range of lines
- Cmd + Shift + P > "Git: Stage Selected Ranges"
or in multiple steps (I usually do it like that):
- Select the first range of lines
- Cmd + Shift + P > "Git: Stage Selected Ranges"
- Select the second range of lines
- Cmd + Shift + P > "Git: Stage Selected Ranges"
Aware of this, and tried it. However much of these distributions is streamlined towards EVIL keybindindings so you don't really get the full experience. Furthermore, a lot of the Emacs keybindings have been opinionated, which again isn't bad but a little jarring.
Also the vi keybindings tend to reactivate every now and again, and often you can take a few goes to realise this as you fumble in frustration and lose your train of thought.
> It relaxes the learning curve.
Yes but you'll have a learning curve either way, and by the time you've passed it you'll know neither vim nor emacs, and you won't get to experience the joy of tailoring your own development experience nor will you have be able to make use of much of to the decades of support content that's available on the web.
As I said, it makes more sense if you've already worked with VIM and want to have the best of both worlds but even then I think you're still missing out on some of the finer experiences Emacs has to offer.
Disagreed with "start with Vanilla Emacs and build your own config" though, if you just want to get started quick. Hell no, you'd be discouraged within the first 5 minutes and spend all of your time searching which ctrl-alt-meta-whatever to press to do trivial things, or copying/pasting obscure elisp snippets that you don't fully understand from stackoverflow.
That was my point when I said
> if I was coming to emacs from VIM ... if you want to do emacs from scratch it’s probably easier
There is no quick start with any of these environments .. and even then it takes some detailed technical knowledge to get them up and running. They do sure look pretty! Although I found some of the default theming a little hard on the eyes for prolonged work.
> Default config is almost 'good enough'
The problem I had, was that to go beyond that it's a little trickier than what I'm used to, and there really isn't the same degree of support as what you get with more orthodox approaches. Though the community small is it is around these distributions are enthusiastic, helpful and friendly.
Like I say, the whole muscle memory thing feels quite alien at first, it soon becomes quite delightful, but not a lot more difficult to learn I think than VIM. I do like VIM, and there's many occasions where I'll use that for a quick command line based edit, and perhaps at some stage I will learn the VIM keybindings properly to the point where EVIL mode makes more sense.
I wouldn't gripe too much about the complexity of emacs, since that's where a lot of it's power lies (even if I never fully use it myself), but I wouldn't be in the habit of just copying/pasting random elisp. Usually if you've to go that much trouble it's not worth it, as somebody would have made it easier already.
alias magit='emacsclient -t -c -e "(progn (magit-status) (delete-other-windows))"'
Is magit good enough to actually force people to learn that little bit of Emacs?
I wish magit-forge [0] had more features though - like I cannot create new labels from it.
Please consider donating [1] to the developer if it has made your life any easier.
[0] https://github.com/magit/forge
[1] https://magit.vc/donate/
git add -p
Then you can decide if each hunk is staged or not.
Just select any parts of the diff using regular edit text select commands and press "s" for stage.
It’s not hard (`git add -p`) unless you need line-wise selection.
The main issue in my experience is that it’s completely linear so you need perfect memory and to never make any mistakes: git shows each hunk individually and tells you to make your choice before it shows the next, no take-backs.
Magit shows the entire diff and lets you jump around, and selectively unstaging is just a “d s” away.
As someone without perfect memory and makes mistakes, I consider git add -p ergonomics very user unfriendly. But I guess that's your point :)
I also routinely use line-wise selection and often revert unnecessary lines when crafting the index.
That requires finishing the current staging, moving to unstaging, processing the unstaging (also a linear hunk-wise process), restarting the ataging, and remembering to skip the stuff you’d mistakenly staged.
The workflow of magit is much easier here, and the staging / unstaging integrates very well with reviewing the local or staged diff. Crafting good commits has way less friction and error recovery is much better.
For example, the fact that you can just jump around the buffer and stage/unstage things as you go, means you're free to use whatever you most like for that "jumping around" part. Incremental search? Sure. Ace-jump? Yes. M-x occur? If you must.
Magit on a bare-bones Emacs is extremely ergonomic on its own, but if you use and adapt Emacs for yourself, all the improvements compound on each other.
In my eyes, however, staging/unstaging/discarding changes to particular lines or chunks of code, as well as having visual diffs is a really useful use case for GUI solutions of any sort.
EDIT: also, it isnt 'line-by-line'. Its logical-chunk-by-logical-chunk. The algorithm will try to group local changes together and you need to explicitly tell it to split the chunk up if it is over eager.
The hunk algorithm is not very good in my experience and following the prompts to split them is just about as nice an experience as editing files with `ed`.
Have you tried using a GUI or an editor that supports staging selected lines?
I use it everyday and it's pretty awesome.
e.g. with tig, you invoke "!git commit" by pressing C from the status page.
With magit, from the status page, commit is performed by pressing cc. But, if you press only 'c', a context menu is brought up which shows the flags which can be set, and commands which can be run.
e.g. 'cc' is 'commit', but 'ca' is 'amend'.
e.g. An example of a flag might be "--force-with-lease". So, press 'P' opens the push context menu, '-f' enables the "--force-with-lease" flag, 'p' pushes to the remote. (Or just 'P-fp' quickly works, too).
tig looks like 80% of the benefits (much nicer to use than git) for 20% of the effort (not having to learn Emacs).
https://github.com/TimUntersberger/neogit
Similar Git tooling can be found in https://github.com/frontaid/git-cli-tools
https://github.com/tpope/vim-fugitive
It reads like it wants to convince you to try magit, without demoing a single example of how it's superior.
It also sounds magical in the worst kind of way.
Also, while in magit, you can type `?` to see the list of available commands from the location where you're pointing at... the commands are single-letters, so you normally do `?`, find the description you want, type `p` (push I think!?) or `c` (commit) or whatever... it's really easy and convenient.
Git is full of that kind of thing. Tealdear and friends usually save me from digging through SO posts or manpages, so remove much of the pain, but it's still worse than having a reminder already on the screen.
(actually, some kind of automated tealdear in a second term or tmux pane, reading what I'm typing with some kind of auto-complete magic so it can show me options quickly even for longer commands, and smart enough to look up "git rebase" as "git-rebase" or whatever, would be amazing... I'll have to look into that)
I regularly do things like "stash some of my changes, switch branch, cherry pick a commit, switch branch, do an interactive rebase reordering commits and dropping one, pop one of my stashes", and they become routine, so working with code becomes a fluent experience, rather than fighting with your tools.
I would say that Magit and structural editing using Paredit are the two most important technologies that make programming great.
Reminds me it's time to tip some projects.
My 12 year old uses magit as a git interface and nothing else in emacs. That’s not a great testimonial as it was my direction to do that, but it seems to work just fine.
The areas where magit earns outsized praise is not around a basic “pull, add and commit everything, push” workflow, but rather around being selective about crafting self-consistent but single-theme revisions. That will not be as fluid for someone with no fluency in emacs keyboard navigation, but I think I’d still find it easier than using the git command line to do it. (Hard for me to say with 30 years of emacs in the rear view.)
Actually, I think git's got Magit beat on that. Magit might make it easier to stage specific lines, but git can stage specific parts of lines or even changes that are completely different than what's on the worktree, through the editing of diffs with `git add -p`'s `e` option.
(Ediff is a 2-way / 3-way interactive diffing interface, built into Emacs, with plenty of features for surgical diffing of files, buffers, directories and whatnot.)
This is news to me.
> select the section you want to stage and press 's'.
It stages line-wise for me. How do I get it to stage less than an entire line?
I just updated magit, too. It seems to have been published 3 days ago.
I could swear I remember this working in the past, but I can find no hint of it in a few quick searches, so I'm likely mistaken.
I'm sorry for the misinformation. Thanks for saying something.
I could swear I remember this working in the past, but I can find no hint of it in a few quick searches, so I'm likely mistaken.
I'm sorry for the misinformation.Thanks for saying something.
After hearing so much good of Magit in a previous thread here I thought 'ok why not?' and installed emacs and magit. That alone wasn't a walk in the park as I never used emacs before. Maybe I did something wrong but what I remember from it is mainly 'wtf x 10 and what kind of documentation is this'. After some hours I got the hang of it, and I see why it is liked, but still it didn't make me any faster with git because I already have everything needed for my main workflows (SublimeMerge + aliases). Also felt like to get any real value from it I'd need many extra hours on the learning curve and it wasn't clear to me whether the end result would actually be better than what I do now. So I skipped on it, but again: I fully understand that if you use emacs anyway it would be crazy not to use magit.
It's just keyboard oriented, text-light interaction design if you will.
invoke versionning (key 1), see what's changed, pick the parts you like (few navigations keys and 2 keys to pick/unpick), invoke commit (key 4) write and accept (key 5) (amend is key 6 if you made a mistake)
It's just fast, lean and tailored. Apparently people did it in vi too. I just wish it was the case in more places. Actually, whenever I write a vuejs thing, I try to embed keyboard as much as possible.
https://marketplace.visualstudio.com/items?itemName=kahole.m...
> working with code becomes a fluent experience, rather than fighting with your tools
I also do this regularly, but on my terminal. I don't feel like I'm fighting the git tools. Is this a common experience?
I enjoy using git GUIs as well, especially for visualizing branches, commits and diffs. I just don't understand why the git commands seem to cause so much trouble.
After the pandemic started and I had to witness over screen share how colleagues "use" (fight) git with all sorts of GUI tools, I had to realize that no GUI can be good enough while one doesn't understand git, or, even worse, it can be contraproductive, because people using these GUIs _think_ they understand, but they don't.
I even ended up creating a (tailored) 2x90min git course...
All that said, I heard magit praised so many times, I still have some hope that it's really as good as its reputation.
(Tried fugitive, which is the vim-world's answer to magit, even learned it properly but realized I always juzt <C-z> to the terminal and do stuff with the cli)
https://eagain.net/articles/git-for-computer-scientists/
I'm not a computer scientist and I think it's understandable. Everything became a lot more clear in my mind once I understood the inner workings.
The git tool itself, though, often operates at a much higher level of abstraction. I think that's more where the reputation of being hard to learn comes from. For instance, you'd probably need to write a paragraph or two to explain what "git checkout <branch>" does in terms of the actual object store. Add to that that the CLI is poorly designed - many commands have misleading names, a given command will do completely different things depending on the flags, there's a lot of implicit / counterintuitive behavior, and so on. See https://stevelosh.com/blog/2013/04/git-koans/ for some funny examples.
https://git-scm.com/book/en/v2
1. Discoverability. It'll display the contextually relevant options and commands at most points. By using magit, you're learning the git CLI commands at the same time, including commands that you'd normally never come across without a comprehensive read of the manual or release notes.
2. Fewer keypresses. Also, extra shortcuts for some common operations.
3. The bits that CLIs aren't very good for: staging and unstaging pieces of files, viewing conflicts.
(I do still use the Git CLI a lot of the time too.)
I also think that the experiences of:
* looking into a stash and applying only selected changes from it, * browsing all your changes and staging only some of them, * quickly killing changes that you simply want to drop, e.g. not commit and remove from your edits
are much slower when using the command line.
Staging part of files is the only thing I found hard with cli but then fugitive or simply git difftool helps with that too (using vimdiff)
For everything else I defined my own git aliases (git graph, git mr, etc)
sounds like hyperbole but it's not.
edit: magit is like if you spent months crafting a bunch of aliases for the command line and then made a nice little menu of all of them and committed that to memory but also has it as a popup. and even then magit is an order of magnitude better... handily so.
Examples where undoing an operation looks totally different to doing it:
- To stage a change you `add` it, to unstage you `reset HEAD`
- To commit you `commit`, to undo a commit you `reset --hard HEAD^`
The last example is also where you get pointed to an unsafe command for a fairly benign operation. Uncommitting is not particularly dangerous, but anything with `--hard` ought to give people a pause for thought. If you mistype it and nuke more than the last commit, that's also a bit bad - and fairly easily done.
Some other examples include shenanigans around pushing and pulling remote branches. After 10 years of using git, I still need to google it each time.
I think these commands are an accurate and reasonable representation of its inner state, but IMHO users should at least have the option of being somewhat isolated from it. Git is not a tool for algebraic manipulations on directed graphs, it is a version control software.
It has to be said, to git's credit, that although the commands are confusing to some (myself included), the tool works very well. I wanted to like mercurial more, but ended up going back to git, as much as I dislike the UI.
The last example is also where you get pointed to an unsafe command”
Who pointed you there? If I want to undo my last commit, meaning the commit itself, not the changes to my file tree, shouldn’t I say `reset --soft`?
But this in fact reinforces my overall point. I don't want to be messing with `reset`, hard or soft. What is `reset`? [I now know because I had to learn, but I'd really rather not].
What I want is `uncommit`, or something like that.
On the plus side, Git’s man pages are (sometimes) useful and pretty complete. In this case, if you type `man git-commit` you’ll get a thorough rundown of all the options and it will be clear which one you should use to get what you want.
EDIT: Also, since there are three arenas to keep track of, the file tree, the index, and the commit history, even if there were an `uncommit` command it would need all the flags that `reset` accepts. So it would just be `reset` renamed, which you can do yourself. But maybe some of the `reset` options should be broken out into separate commands.
But, if you haven't pushed something up to a remote, the right command to make more changes is to use `git commit --amend`.
That's another pet peeve (though maybe less git's fault): immutable, yes, but then rebase is pushed quite liberally. Arguably not by git itself, but by many online learning resources.
It's convenient, and mostly works, but then occasionally really stings you.
...yet undoing the last commit, arguably the least aggressive of history-rewriting commands, remains awkward.
"History is immutable" is generally accepted as describing the contents of commits, not their id's or relative ordering.
Perhaps git should have a "checked rebase" command that requires a `--force` flag if there's an upstream branch set.
*And even then it's kind of okay as long as no one else has made commits on top of the rebased commits.
Which BTW I learned it exists when magit switched "p -f u" to use it instead of plain --force.
For me, this is where the problem with got lies. I use so many of it's commands infrequently enough that I don't know where the weird disastrous edge cases are, where I should use.
I think git would greatly benefit from a topical man page; a list of common and uncommon situations that shows the recommended commands for solving them, and explains what those commands do. I know that hundreds of random "guides" exist, but are they outdated, are they cannon, do they have bugs? When your UI is esoteric, situational documentation is really important.
If git at least had good man pages. The man-page's description is "Given one or more existing commits, revert the changes that the related patches introduce, and record some new commits that record them." [1] I have a hard time parsing that to mean what it's supposed to mean.
It contains a note that's much better at explaining what git revert does, then goes on to explain alternatives for other things you might want to do, but doesn't mention how to undo a commit without creating a reverting commit.
1: https://git-scm.com/docs/git-revert
Can’t disagree. That part could certainly be written better. I’m not saying I would want to learn Git from the man pages, but they’re pretty good in general after learning it elsewhere.
1: https://git-scm.com/docs/giteveryday
2: https://git-scm.com/docs/git-rebase
- git revert {rev} to nuke changes and go back to how the world was
- git uncommit to return to the state literally before git commit
- git unstage to unstage a file
The latter arguably should go with git stage but it’s a bit late for that. NB git add and git rm are totally not inverse operations...
So then I can uncommit, and unstage if need be. Reverting is for discarding changes, and should come with an interactive confirmation prompt and other safety and hygiene messages.
This is ambiguous because there are many such states.
1. Clean working tree, before you began hacking on the code.
2. Modified working tree.
3.1. Modified working tree with staged changes.
3.2. Clean working tree with staged changes.
It's impossible to know which state you want to go back to without telling git. That's what hard, mixed and soft resets do: they bring you back to states 1, 2 and 3.2, respectively.
The default is a mixed reset. I suppose state 2 is what most people want when they try to undo a git commit. So it already does the right thing by default, no?
The only remaining problem is the git reset argument. An undo command will always reset to the previous commit, there should be no need for arguments. Stuff like HEAD^ or HEAD~1 is quite obscure to the uninitiated. We could certainly have a git undo command that runs git reset HEAD^ and allows hard and soft resets. Not sure why it doesn't already exist. Has anyone ever attempted to get that merged into mainline git?
[alias]
undo = reset HEAD~1 --mixed
Glad you found something that works for you but this is definitely not true for all of us.
I think the problem with add, commit and reset is they aren't low level enough. The reset command in particular is juggling several concepts at once: HEAD, the index and the working tree. The add and commit commands work with fewer concepts: working tree to index and index to commit, respectively.
I too google the commands I don't use often. There's no shame in that.
> I too google the commands I don't use often.
So, spend more time getting the same result is fine for you?
Sometimes I have to use some command I'm not familiar with. Sometimes familiar commands gain new options. It's perfectly okay to use some reference for that. Also, "more time" is like 1 minute.
If you ever run into this, you can use `git reflog` to see the history of your local actions. It's possible to revert almost any action with it.
Reset a few commits that you've never pushed to remote? No worries! Just go to `git reflog`, find a point before it happened, and `git reset` to it.
And you're back before "OOPS" :) It's really hard to lose changes once they've been committed.If you don’t know git internals, mistype a non-obvious command and lose a bunch of commits, then “look in the reflog” advice is frankly adding insult to injury.
What's right for one isn't right for all.
I want to get things done fast and with less cognitive load, magit allows me to, git doesn't.
I've still managed to do it (or maybe I used git rm to delete some files that weren't committed?) so let me give one more shout out to 'git fsck' which saved me here.
Git is garbage collected, even if a commit is dropped from a branch it won't simply disappear immediately afterwards. The object is still in the git repository and it can still be reached, most easily through the reflog. Only when garbage collection is performed will any unreachable commits be deleted.
You're not meant to delete commits like that. Git encourages you to stop "lying about the past", and you will run into a fair amount of trouble if you try to do so with shared history. You don't remove a commit "backwards" and change history; you add a new commit that undoes the previous one (git revert)
Couldn't disagree more. To me, one of the massive advantages of Git over other VCS tools is the support and completeness of its ability to edit time. You are the editor not just of the content under control, but over its branched evolution. Accepting this and working with time gets you to a next level of control.
The first step in this process is really internalizing the tree of commits, and seeing branches not as lines of development as much as simple pointers on that tree. In many VCS systems, branching is a big deal. In Git, a branch is just a smart tag that is automatically updated by HEAD. Users new to Git need to get comfortable creating branches at a whim as the tree grows.
The next step is getting comfortable with editing the tree itself. Primarily, I recommend using interactive rebasing liberally. This has multiple positive side effects:
1. It causes the author to think at a higher-level of the primary artifact they're constructing — the tree of incremental changes.
2. Authors begin to think about the repository as more than a dumb file backup system, but instead as a history with true utility, and so begin to construct "stories" in that evolution that are instructive and useful to future readers of that history.
3. It takes the author out of the flow of time, and encourages them to think about ways to change the past (within limits, of course) so that the constructed history is improved.
All of this, of course, with the caveat that shared history changes must be coordinated (and frequently avoided). You can get very far thinking this way just about your un-pushed topic branch.
There's a very real philosophical difference between those who see VCS as a secure audit trail (where changing history is "lying about the past"), and those who see a repository as a whole constructed artifact of intrinsic value, wholly editable as its contents. In this latter view, editing a line of source isn't "lying" about that line's contents, and neither is editing time.
I did specify that rewriting shared history is going to cause you trouble (unless you really know your way around things), but apparently it wasn't clear enough
After trying a couple of times, I haven't been able to get used to magit, and I gave up. I'm very used to the git command line interface, and magit is just too different from that. For instance, it seems to assume I want to operate only on a file, whereas most of the time I want to operate on the whole repository. I have no idea why someone would want to work like that.
I found it was taking a lot of extra research to get it to do what I wanted, and I was completely confused by its choice of default behaviours, so I gave up trying. I would welcome an interactive tool that is more oriented around the way the command line tooling works, but magit does not seem to be it.
I do have magit installed however, because I really like how it controls emacs buffers while using interactive rebase. But I never use the rest of it. I have no interest in trying to memorize which hotkey does what, and how to bend yet a new interface to my will (that apparently disagrees with my preferred default behaviour), when I already know the git command line.
you don't have to, most of the time `git subcommand` counterpart is just `M-x magit-subcommand`
There is also nothing wrong with copying your entire tree to a different directory, diffing, applying patches by hand, and keeping track of what goes where.
Those are different levels of automation for the same fundamental task, but they are all legitimate solutions to the same problem, although you might end up spending more or less time to perform the same fundamental task, depending on the level of automation.
What? There is plenty wrong with that. I've worked with people who did that. There are lots of problems with this approach. It's extremely hard to work with and it only gets harder the more people are involved. At least in git the commits have unique identifiers, everything is hashed and checksummed automatically, branches are properly tracked, etc.
I've even worked with non-programmers whose version control was emailing each other files named like:
It was a hell unlike anything else I had ever experienced before.All that means is that git tools, and your front door, work well once you have mastered them. The ease of use and discoverability of tools over the life of their learning curve is what determines if they are a Norman door.
For lots of people, using a Unix command line or Git for the first time feels like a Norman door. This is why other interfaces exist (like guis) for the same tools.
What is a Normal door - 5 min Vox short https://youtu.be/yY96hTb8WgI
My big hang-up with interactive rebases is that I do them just infrequently enough that what exactly a set of choices will yield—what's going in the commit message, et c.—is something I have to sit there and reason about for a really long (by the standards of something that really is not that complicated an operation) time. I can also never keep it straight when editing messages in-line will have an effect, and when it'll be ignored (in some commands it is, IIRC, in others not? I can never remember, but either way, why the hell let me edit it if it won't do anything?)
What I could really use is a live preview of what the effects of my current choices will be.
If I want to rebase changes onto a different commit, re-order them and squash some of it, I'll rebase as-is first, then do another rebase and reorder everything so that squashes are next to each other (and yes, sometimes this means unnecessary conflict resolutions), then a final rebase to squash. I'll edit messages last.
Yes. Today I spent way too much time explaining to a coworker that what he was complaining “should be easy to do but seems impossible” was actually quite simple, only to spend ages explaining how git works, why he wasn’t understanding the paradigm. And after all that help what he needed to do was simply to “git checkout feature-A && git merge master” we didn’t even touch on rebasing, and it’s not like he hasn’t used git before, he had at least half a decades worth of experience working with codebases managed in git.
And this is far from the first time that I’ve had to help out people with something that seems extremely straight forward to me and others who have git under our skin, but is overly complex and difficult to people who might not be experts but have worked with git for several years in a state of “minimal viable knowledge”.
Git has the same problem as it’s creator, it is arrogant, and has for way to long tried to explain the fact that new users find it difficult with “well they are just dumb” instead of accepting that it needs to make its user experience and interface more intuitive. Some of these changes are finally happening now, so I no longer have to explain why “git checkout” is used for seven completely unrelated things, but there are still tons of cases where the “straight forward way” to do something is only accessible to people who have spend way too much time doing deep dives with git and fully explored all the edge cases just for the fun of it.
It doesn’t help at all that googling issues is swamped with advice of “just force it” or “delete the repo and clone it again” which can cause permanent damage to the codebase, for a tool that is at its center suppose to avoid permanent damage to your codebase. No matter how stuck up some blinded advocates of the “git is and has always been perfect”-camp you are, everyone should understand that needing to give advice like “and if you have an issue don’t Google it, go see me or another git expert first to avoid loosing code history” is at its core spotlighting fundamental issues in the tool interface.
Isn't there some middle ground between "minimal viable" and "expert" that you could (should) aspire to, like "reasonably competent"?
I think it's not a matter of "just" a version control system; it's vital enough to (most of) our jobs that being more than just "minimally viable" good at it is an integral part of being reasonably competent.
But who am I to talk; at work, I almost exclusively use Informatica's built-in "version control system", which IMO... isn't much of one; actually, hardly is one in the first place. Getting to use git (or similar) again is what Idream of. Then again, maybe that just means I'm only "minimally viable" with Informatica's system. :-)
(All out of Spätzle, have to wait for next "Alpenfest" week at Lidl. :-( )
To me the git command line is one of the tools that are great if you use them often. But if you use it less often it's really hard to remember the correct syntax especially since it's really easy to mess things up. (If know WPF, the binding syntax is in the same category. Really powerful but if you take two months break you struggle with the syntax). It really bugs me in git when normal things need 3 or more parameters and if you forget one of them you mess things up.
Years ago I worked with mercurial for a while and I thought the commands were much cleaner and easier to remember.
But there is one thing I believe is still not-very-smooth in the git cli: splitting hunks.
if I do interactive add in git, and I get small hunk that adds a line, deletes a line, adds another line, and deletes a line, then if I want to include only the addition of the second line, it is pretty annoying in git cli. In magit, it is basically selecting the line and pressing "s".
I don't feel like I am either - I think some people are not fans of CLI. Full disclosure: I also don't "get it" when people say they can't use tar without looking up the help/man pages.
I get by with less than 10 git commands - in rough order of decreasing frequency: pull, commit, add/rm, push, stash, checkout, merge, and more rarely bisect, revert and reset.
Trying to stash some of the changes is pretty annoying, yes. New files don't want to cooperate with stashing, and there's no way to stash just staged things like making a commit; you have to use -p.
That would be a nice feature!
Or use magit that has a stash index option.
I would also add undo-tree to that list, it's like having a lightweight VCS on every file without needing to resort to git.
That's interesting because those are two tools I've tried to adopt multiple times, but never have managed to do.
Paredit is at least partly due to my long use of vi (and almost as long use of vim) keybindings; I use evil-mode, and bind << and >> to the appropriate adjust-parens functions for strucutural editing.
Magit is due to me having used git for so long that it takes me at least 5-10x as long to do something with magit as with the git terminal, and I'm just not at a point in my life where I desire to fight with my VCS when there is another option.
I suppose I'm just stuck in local maxima with regards to those two things, but I'd say I'm fast enough.
People should try this kind of thinking instead of big engineering principles that only slow the machine and the user down.
It's only the 13th time I wrote this.
I'm using magit, along with tig, plain git and sometimes (!) even plain "vc", depending on context. I'm in the camp that thinks it's ok and it's pretty comfortable to use within emacs, but I don't see the earth shattering praise I see every time it's mentioned here.
Tig for example is so much faster for history and blame perusal that I find it faster to keep it open in another terminal and just switch to it.
Altenatives? Contrarians?
Maybe the reason is another? Personally, I once had Magit act real slow at times because git-annex had added some git hook for something that I didn't need. Just removing that hook improved performance massively. Perhaps something similar is happening.
Also, I'm not sure Emacs Lisp can interface directly with C libraries, so using libgit2 might not be an option.
I only work on Emacs in small projects though... so maybe that's why it's fast for me?!
I believe these days (i.e. since emacs 25) it can via dynamic modules. There are ffi libraries built on top of it.
In a perfect world, Emacs would link to libgit2 and Magit would be adapted and folded into the core distribution.
Whatever is causing the slowness you're seeing, I don't think it's just because of the number of calls. It's probably the slowness of one or two specific commands, perhaps due to repo size.
Seems like there's something going on in the windows world.
However, my own cited example about browsing history and blames is one case where I cannot just stomach the subpar efficiency. Tig also runs git as a subprocess, but every view is truly incremental and you can scroll through any buffer in any view and there's absolutely zero delay. Night and day even when comparing emacs with JIT.
Like for magit, tig has one keystroke shortcuts that make sense (which IMHO is pretty common on good TUI programs) and can perform many git operations directly from the spot you're looking at.
I also consider the visual space usage in tig to be much more efficient as well. Especially the blame view, which I find still wasteful in all modes compared to tig's. I frequently use a customized vc-annotate instead.
Magit hooks also considerably slow down operations on remote files, which can be quite annoying if you don't actively need to use git while editing.
Don't get me wrong - I like magit. But like org-mode, I don't get the glorification it gets.
- I generally dislike layers on layers; while I seriously hate the git UI, I'd rather learn that, as it's a more portable skill, than learn another UI, that relies on emacs and a package installed. First thing I do on e.g. a new cloud instance is clone a bunch of stuff, and often work on an under-setup machine for a while. For similar reasons, I don't use shells like Fish, which, nice as they may be, funnel me into something totally incompatible with good old sh. Bash and zsh, as far as I use them, are compatible.
- I work in tmux, and emacs in terminal, the overhead of switching to a terminal and typing some git stuff is tiny.
- I tried magit and just didn't get it. I couldn't couldn't find a happy path where I thought, "ah yes this is niice".
I mostly use plain git instead of Magit, for more or less the same reason, although I like git's UI.
I did find a happy path, though. Magit's blame interface is very nice to recursively call git-blame and navigate history of pieces of code. I ended up making a CLI program to improve git blame[1] so that I didn't end up switching to Magit just for that, but doing git-blame from Magit is still better.
[1] https://github.com/jolmg/git-reblame
I'm surprised to hear this. Magit is a very thin layer on top of git. Not thin in the technical sense, but in UI/UX sense. Keybindings map almost one to one with git CLI. Arguments to the git CLI are explicitly stated. Executed git command is reported. I learned git better by using Magit.
FWIW, most Magit commands have 1:1 correspondence with git commands; when I'm worried I'm doing something with Magit that I wouldn't be able to replicate with CLI, I just press '$' to pop up the "process buffer", i.e. the buffer containing actual git commands being executed, along with their output. Conversely, I still read git documentation to figure out more advanced Magit workflows.
My way of looking at it is, Magit is just an ergonomics layer on top of git - it doesn't introduce new abstractions, it just lets you do stuff in a more efficient and interactive way. The love comes from that efficiency - the improvement is big enough to make a qualitative difference and affect the way I interact with git.
(And, of course, you can just press !! and type in whatever git CLI command you want, to run in context of your repository.)
> the overhead of switching to a terminal and typing some git stuff is tiny.
Switching cost is low, but typing cost is much greater.
Of course, everyone has their own preferences. I personally swear by Magit, and I'd love to have more command line tools be integrated with equivalent interface. Magit's UX paradigm isn't a total replacement for all CLI - but it's perfect for tools you repetitively invoke with different parameters to sculpt something.
That typing cost is why I use a GUI. While many times I can just enter `git add -u` into the terminal, there's still plenty of times where I want to be selective about what goes into the commit. If a simple glob pattern can't do it, then I'm going to reach for the GUI where I can just click on all the things I want to add to the commit in far less time than it would have taken to type all of the file names.
The GUIs also keep me immediately informed on the state of my repo. On the terminal, I'll be running `git status` a lot, just to be sure the state I think the repository in in and the actual state match up.
The popup-based paradigm for keyboard operation helps with discoverability - first few times around, you'll be going slow to learn what key does what, but after that, you'll be issuing most commands from memory.
The key point I was trying to make is that an interface that minimizes the amount you need to type out and that gives you instant feedback to your actions is a superior experience for working with Git in many cases. I say this as someone who uses Git from the command line a ton (to the point where I've added some custom command scripts) but then when I need to do anything complex or browse the logs and diffs I'll enter `gitex` to bring up the Git Extensions GUI.
I prefer IntelliJ's git interface.
Magit can do everything IJ can, but in IJ, I can find how to do things more easily and it just feels easier to do things, probably because it's much more GUI than text compared to Magit. For example, difficult merges are extremely easy in IntelliJ, I can edit code in the diff view itself while I resolve conflicts... in Magit it requires getting used to the different diff views, something I am still trying to figure out, but it seems trickier to do "in-place" changes in the code.
That said: I probably only prefer IJ because I've been using it much longer than I have used Magit... and the difference for me is very small, so I suspect the more I use Magit, the more the gap will close and I may eventually like it even more than IJ.
Not the biggest deal since neither of those commands require interacting with the output which makes them equally easy to run from the terminal, but it's strange that they're not available in an immediately obvious place.
In the lower right, there's the vcs "where you're at" that shows the current branch. From there you can see the status of your branch compared to others (if you need to fetch them), or you can update branches (even those you're not currently on) along with branch specific operations including push. You can access the same in the git panel with right clicking on branches in the log.
At any time, you can double tap shift to bring up the "search everything" window. Within that, if you type "git push", it will display that action along with the menu that action is in and any key shortcuts that are bound to it.
Also, glance under the "Help" menu - there's a productivity guide. That shows you a whole bunch of features (and how often they're used) and how to use them.
Maybe you disabled the git toolbar in the menu?
There's a little bit of discussion on it.
Its UI for resolving merge conflicts is so intuitive and powerful. You get 3 panels: local changes on the left, remote changes on the right, and merged in the middle. It's got colored highlighting going across from each of the side to the middle, showing where the changes want to go to, and you click arrows to accept/dismiss left or right, and sometimes it'll even have a suggestion for a way to take both of the changes (indicated by a magic wand). And you can also just type into the center editor if you want to not use either side, and manually rewrite the resolved change yourself, whether that be copy-pasting from each side or whatever you want to do.
It's saved me so many times, it's practically worth the cost of the entire IDE on its own.
It's very cool and flexible and doesn't tie you in to any big tech provider (yay!), but it's just an outliner at the end of the day.
I will say that I won't be using it, as I use GUI tools, with a far smaller "power" level, and use command-line Git for the few times I need anything fancy.
While working on kernel I sometimes get "looks nice, but can you reorder and re-split this 15-patches series in completely different way?" and magit is a big time-saver for that. It wasn't as useful on my previous jobs where 1k-lines commits with message like "Implement feature X" were the norm, though.
interactive rebase: no
cherry-picking: yes
That said, I’ve financially backed Magits development (Kickstarter iirc) and I use it almost everyday, but I don’t do merges with it. I’ve had some large merges go really slow thru Magit. So I always do my merges in the terminal using the plain git CLI.
Sublime Merge and vscode + git plugins are pretty close to each other but Sublime Merge does everything I need with less fuss. vscode just has some rough edges due to it's swiss-army knife approach that Sublime Merge doesn't.
But does it make me much more productive? I don't know.
While developing typically I add some debug code mangled with the actual stuff. So when I am ready to commit I've got to remove that first. I had done this manually in the editor before, now from within magit I can just select the lines I'd like to stage and press "s". Then proceed to commit pressing "c". Finally, by just selecting the remaining lines and hitting "k" ("kill") I get rid of all debug code. That's pretty nice and I will never ever forget to remove debug code again. Similarly, you can manage your git stash with a couple of key strokes.
Branching and merging works well, too. But I don't think magit makes it much easier as you still need to type in branch names. Autocompletion is supported, but git provides this as well.
Merge collisions are still a pain. And for more complicated tasks like interactive rebases, reflog rescues or bisecting I still keep dropping to the shell. I actually like the expliciteness, here, because it prevents me to stupid things in dangerous maneuvers. And "git help" is always there to remind me on all gazillion command line arguments.
But yes, I do drop to the shell for some actions when I know exactly the sequence of git commands that I need to execute. Also somehow I often use the shell to switch branches, some habits are hard to change.
Same here. I've found completing-read for branch names to be one of the biggest draws for Magit, personally. I can tab-complete them in my shell, but it's much slower and less reliable.
git, as a classic unix cli app, doesn't provide autocompletion
git, as a classic unix cli app, doesn't know nothing about the result of a previous command, etc.
These aren't the git flaws, but Unix ones.
The only downside I have for now about magit is when using `pre-commit` it can run for long sometimes, so it would be nice to see the progress/output of pre-commit while waiting for the commmit message buffer to appear. If you know a way I'm all ears.
Also inspired me to try out Emacs but that's a longer story
Compared to opening up Github, or stashing and checking out via git manually, it was so much faster.
And I have no idea how to use emacs. Is there any helpful user manual? Should i give up on magit?
[1] https://magit.vc/manual/magit/Getting-Started.html
The learning curve is fairly steep in the beginning, but after ~15 years, I feel that the initial effort has paid off a lot. Not everyone likes emacs, and that's okay. But I do think it is worth giving it a try and seeing for yourself.
(As for the whole vi-vs-emacs debate, I have used both over time, and I do use vi quite regularly for quickly editing some config file. There are packages for emacs, like evil-mode, that emulate vi's key bindings and behavior, but I have not tried any of them.)
Then you're in the magit window with menus and prompts and so forth.