7 ms·
> There is no staging area. That's actually a deal breaker to me. Effectively using Git's staging area has become so integral to the way I work with repositori
by chungy 4y ago
> There is no staging area.
That's actually a deal breaker to me. Effectively using Git's staging area has become so integral to the way I work with repositories that I don't think I can ever go back to the old style.
- masklinn 4y agoMeh. If it has mercurial's revsets instead of gitrevisions(7) I'm game, I'll happily give up the staging if I don't need to open that manpage ever again. edit: yep, so long git check if a given commit is included in a bookmarked release: sl log -r "a21ccf and ancestor(release_1.9)"
- chungy 4y agoIs it really that confusing for Git? I had basically that entire manpage memorized early on (even before the manpage existed....)
- masklinn 4y ago> Is it really that confusing for Git? Complete shit is what it is. It's awkward, messy, inconsistent, and hard to compose.
- IshKebab 4y agoThe CLI and nomenclature for the staging area (what should be called "draft commit") is awful, but the actual concept is very easy to understand. I seriously doubt anyone who uses a sane interface to Git (e.g. a GUI) has any trouble with clicking + to add changes to the draft commit before committing it. Most GUI tools let you automatically add all changes before committing anyway so you don't have to know anything about it if you don't want to. They just needed to name things better (what is a "soft reset" again?).
- jcranmer 4y agoThe main problem I have with the staging area is that it amounts to being something that's like a commit except for, you know, not actually being a commit, and therefore things that normally work on commits don't necessarily work on the staging area. A better fix would be to make the staging area an actual commit, and then reframe everything as easy ways to edit the latest commit. (This meshes well with adding features like Mercurial's phases or changeset evolution that make commit editing somewhat safer).
- still_grokking 4y agoA "draft commit" (I really like that name!) is not a commit, and should not be handled as such. This would make this feature more or less useless. The whole point of the "draft commit" is that you can easily see changes against your (uncommited!) changes. That helps to build up a commit step by step. Committing WIP stuff (and maybe even pushing that) makes the history useless. Branches don't help as you end up with millions of WIP branches that are all incompatible to each other (and the evolution that happened elsewhere). Only keeping WIP branches up to date is a full time job than. Git has already a means to edit the latest commit easily: `git commit --amend`.
- jcranmer 4y ago> The whole point of the "draft commit" is that you can easily see changes against your (uncommited!) changes. That helps to build up a commit step by step. > Committing WIP stuff (and maybe even pushing that) makes the history useless. Here's the thing. I'm a very big proponent of keeping history clean, and making sure that commits are atomic, and exorcising any "typo fixes" or the like commits from history. Not once have I found the concept of a staging area useful. Features like `git commit --amend` or `git add -i` are incredibly useful [1]. But not the staging area itself--it's only a thing that screws me up if I forget to add `-a` to `git commit`. "Draft commit" also I think elucidates the other problem. You see, drafts of regular documents are frequently shared with other people, multiple versions of them created and shared, etc. Drafts don't become final until it's actually published--and there is utility in being able to track the differences in drafts as they are discussed. If you've got a "draft commit", then it should be able to go through this process--this is basically the process of code review. Of course, we're already working with a VCS, which is designed to handle different versions of code, so... what if we made the "version history" of commits just... regular commits? Sure, shade them a different color, so you know that a commit is a draft, and you can tell which of the commit's parents [2] is the previous version. And knowing that a commit is a draft, when it actually gets pushed into the trunk, you can commit only that final commit and not include any of the previous history. Since the commits are using the same DAG logic under the head, questions like "what changed between version 2 and 5?" become just regular diff commands [3]. By the way, this system already exists. It's known as changeset evolution in Mercurial, and it appears that Sapling here has adopted it. My workflow in git tries to emulate this model to a degree, but the approach of having branches-based-on-branches doesn't mesh well with how git wants to do things. [1] The number of times I have painstakingly sorted out which changes go into the commit with `git add -i` onto to immediately and accidentally undo them with a `git commit -a` is quite high. And because the staging area isn't an actual commit, it can't be recovered by digging into the reflog like actual commits can. [2] If you amend or otherwise modify a commit, it has one parent, which is the previous version; if you rebase a commit, it has two parents, one of them the new commit it's based on and the other is the previous version. [3] Worth noting that this question often turns out to be difficult to answer with most code review systems. Building a model of "commit history" into your VCS makes it come out for free!
- quark12 4y agoYou can also do `sl/hg log -Gr a21ccf+release_1.9`. The graph tells you the relation of selected commits. Last time I checked, git does not have the same --graph rendering yet - it only considers direct parents not ancestors.
- jcranmer 4y agoMercurial revsets and phases are two killer features of mercurial that blows any counterpart git has out of the water. Phases are a property of revisions that essentially let you know their state. By default, there are three phases: public, draft, and secret. You can't rebase a public revision, nor can you have a public revision with a secret parent. So you get out of this concept things like safe rebasing, or barriers that let you keep internal and external repos separate. But revsets really shine. This is basically a full-on query language for revisions. So you can define a query alias "wip" that specifies all of the, well, interesting revisions: every revision that is not in the public phase (i.e., not in the upstream repo), the tip of the trunk, the current revision, and sufficient ancestor information of these revisions that you can see where you based all of these WIP branches on. In a single query: "(parents(not public()) or not public() or . or head())". Sure, composing revsets is definitely a somewhat painful process... but it's possible to describe more or less arbitrary sets with a Mercurial revset, and I've never been able to find a similar workable setup in git.
- oorza 4y agoWhy do you want to? Not trying to be snarky, but I've been using various source control tools for closer to 20 years than 10 and I can't remember when I've ever needed or would have benefited from revsets. I'm genuinely curious what problem this solves and whether I've just never experienced or have made my own hodge podge solution for it incidentally.
- jcranmer 4y agoI am used to working in large repos (>100 commits/day), which generally means that something like 'git log --graph' contains a lot of extraneous information. The most common workflow I have is that I've got a couple of old working branches (like featurea and featureb), and I want to see if I need to update featureb to a newer head or not, or if featureb was based on featurea or featurea-v2. A demonstration of this kind of thing is 'hg wip' here: http://jordi.inversethought.com/blog/customising-mercurial-like-a-pro/ http://jordi.inversethought.com/blog/customising-mercurial-l.... Another thing I would use revsets for is answering queries like "which of these changes that's on the public repository made its way into the internal repository (which periodically merges from the public repo)?"
- sggutier 4y agoWell, sapling kind of supports something like the staging area with the interactive version of some commands (e.g. `sl commit -i`, `sl amend -i`)
- arxanas 4y agoIt has an interactive commit staging command which accomplishes the same thing. In that case, it unifies the staging area with regular commits, which means you can also manipulate them the same way as regular commits. AFAICT there are only two workflows involving the staging area: staging partial commits and resolving conflicts. The first case is taken care of by partial commit support, and the second case presumably has its own dedicated mechanism.
- saghm 4y agoMy favorite example of the staging area being super weird is `git diff` behavior. By default, git diff will show unstaged changes as well as committed changes, but _not_ staged changes; to see staged changes, you need to use `--cached`. This is especially weird when diffing between a fixed point (e.g. a commit hash) while going through the motions. If it's not clear why this would be weird, try out the following: * get the hash of the HEAD commit * run `git diff <hash>` and see that there are no changes * make some change to a file * run `git diff <hash>` again and see the change you made * stage the change with `git add` * run `git diff <hash>` again and no changes are show! * commit the change * run `git diff <hash>` again and the changes are back It's super bizarre to me that there would be some sort of intermediate state where changes aren't visible. I feel like it would make more sense to have some sort of formatting difference indicating unstaged versus staged but not committed versus committed, but I imagine changing that now would break all sorts of scripts, so we're stuck with it.
- sdiacom 4y agoNot to subtract from your point at all, but newer versions of Git allow you to use `--staged` as a synonym for `--cached`. That this is the default behaviour still makes no sense, but at least the name does.
- saghm 4y agoAh, that is a better name! I'll have to add that to my mental list of git UX improvements (I'm also a big proponent of `git switch`)
- thijser 4y agoIt's really just a matter of habit and getting used to no staging area takes short and has huge benefits. We develop HighFlux[1] which also gets rid of the staging area. It simplifies your mental model of what's going on a lot. Because everything you save is automatically committed, switching to a different task/branch is also always instant without needing stash. Because what you're testing locally is what you're committing, I also never have CI failures anymore (with the staging area I frequently had unexpected interactions with unstaged changes and sometimes even accidentally forgotten added files). 1: https://highflux.io/ https://highflux.io/
- still_grokking 4y agoSounds like saying bye-bye to any meaningful history. Rebasing, cheery-picking, or reverting of commits becomes impossible when every save of a file is pushed. You could just publish local IDE history… Would be equally "good" I think. (My IDE is saving files every few key strokes btw; the resulting history would be a bloody mess). Why not go one step farther: Just make an automatic block image of the whole systems of every developer machine every few seconds. You could than just deliver the image. No docker setup needed any more. Just write code. And when the local version works, ship the whole local system just as it is. ;-)
- joshuamorton 4y ago> You could just publish local IDE history… Would be equally "good" I think. (My IDE is saving files every few key strokes btw; the resulting history would be a bloody mess). Google does this, it has saved my butt on more than one occasion. > Sounds like saying bye-bye to any meaningful history. I'm so confused, you just amend the most recent commit, or work with changes unstaged and uncommited. Like my normal workflow is basically "change 2-3 files such that things are passing, hg commit, send for review", and then I continue working on the next thing, either back to HEAD if its unrelated, or on top of the just-pushed changes if it depends on them. It's vastly simpler than having to git add at random times.
- still_grokking 4y ago
- ajkjk 4y agoWeird, it's one of my favorite changes. Finally I might get a version of Git which works without a bunch of extra crap getting in my way! you can always just use another commit as a staging area, I figure, and it'll make all the commands simpler and more intuitive so it wins in my book.
- still_grokking 4y ago> you can always just use another commit as a staging area, And than you have to do gymnastics with rebasing and rewriting history afterwards. Using the staging area upfront is much simpler!
- ajkjk 4y agoOh well, I don't have any problem with that. I like having all my changes always committed though.
- Shish2k 4y agoI use HEAD as my staging area, and do all the normal staging-area things, but without the weirdness that comes from the staging area being a different concept to a commit (ie, the diff command Just Works, no need for a separate `--staged` flag to enable special behaviour for that case)
- deleted 4y ago[deleted]