Gogit doesn’t even support the index (staging area), so instead of gogit add, you just gogit commit with the list of paths you want to commit each time. As pygit’s code shows, dealing with the index is messy. It’s also unnecessary, and I wanted gogit to be an exercise in minimalism.
What a feature! Finally a stateless commit command! Believe it or not, but I have been wanting this for a decade. Thank you for making this, so I wouldn’t have to!
I keep saying that the staging area is a stumbling block that shouldn’t be obligatory to use. It is trivial to squash commits, so it’s not like anyone really needs it to assemble a big commit (modulo self-imposed commit hooks). Rather, this hidden state is a constant source of surprise for us all, since what you commit is not what you see in git diff – if you added, moved, removed or checked out a file yesterday, and didn’t immediately commit or unstage it before you forgot about it, it’s now hidden state, and tends to sneak into the commit that you amend today.
It is trivial to squash commits, so it’s not like anyone really needs it to assemble a big commit
I actually end up using it mostly to assemble small commits: committing parts of my current state at a time when they’re ready, but without having to commit e.g. testing code I still need locally or other changes elsewhere in the file.
I usually abort the git add -p to modify a file slightly before committing, so I don’t do it in one step. I also like to git diff --staged before doing the commit, rather than committing and them amending several times to get it right.
It sounds like what you like about the staging area is that it gives you a notion of draft/private vs. final/public, is that right?
I use that distinction a bit less, or rather more: instead of one staging area in flux, I feel free to edit any commit that hasn’t been pushed/merged yet.
The draft/public distinction doesn’t require an index/staging area: Mercurial attaches it to commits, instead of to exactly one not-a-commit.
Specifically, Mercurial lets you mark commits as being in phase secret (won’t be pushed/pulled), draft (unpushed), or public (has been pushed/pulled).
[Edit because I submitted too soon:]
As for git diff --staged: See how the index concept forces Git to have a separate command? There is git diff for the working directory (but staged changes aren’t really in the working dir); and git log -p for any commit (but the index is not a real commit), so now you need a third invocation. If you sculpt the latest commit instead of an index, git log -p can run on HEAD no problem. (And in my daily work I do exactly this, many times per hour.)
For me, the difference is typically in when I want to remove some diff from my staged changes. It’s pretty easy to git reset the file and redo the git add. I’m not aware of a comparable “remove this file from the commit” command, so if I really need to do that, what I have to do is revert the commit, uncommit the revert-commit to get a negative diff of the commit, remove everything but the change I want to remove, then amend the commit with that change.
Splitting a commit is indeed a missing feature of git rebase, but git-revise has it, and there is a PR to support specifying paths while doing so (rather than answering yes/no to every hunk).
Before that, I also used to do the double-revert dance.
Tip: You can git commit --patch, just like git add --patch. Even with multiple paths if you have. Is that what you mean? It’s not much git add can do that git commit can’t, and it saves a step. Only one thing – committing previously untracked files – which Gogit has now solved.
I also use --amend a lot, or commit many small commits and then squash the related ones. Or if I have no idea to begin with, I just make one big commit at the end and iteratively split out pieces of it with git revise. Which is just as easy as staging out the same small commit from the same set of unstaged changes, with the benefit that it also works with commits that aren’t the last.
I don’t find it that big of an issue. Perhaps it is because I learned to do git status to orient myself, much like sysadmins habitually type ls like muscle memory.
(well, I have alias gs="git status", so it’s not as much typing as you’d think)
Most certainly. I never (intentionally) use the staging area, which is why I have no use for git status. Other than to assert that nothing is staged before I commit. I do that if I’m unsure, but it’s not a habit, which is how it surprises me again and again.
The ls thing is a reason that you shouldn’t actually use the command line for managing novel filespaces. It’s only good for filespaces you already roughly know.
What a feature! Finally a stateless commit command! Believe it or not, but I have been wanting this for a decade. Thank you for making this, so I wouldn’t have to!
I keep saying that the staging area is a stumbling block that shouldn’t be obligatory to use. It is trivial to squash commits, so it’s not like anyone really needs it to assemble a big commit (modulo self-imposed commit hooks). Rather, this hidden state is a constant source of surprise for us all, since what you commit is not what you see in git diff – if you added, moved, removed or checked out a file yesterday, and didn’t immediately commit or unstage it before you forgot about it, it’s now hidden state, and tends to sneak into the commit that you amend today.
I actually end up using it mostly to assemble small commits: committing parts of my current state at a time when they’re ready, but without having to commit e.g. testing code I still need locally or other changes elsewhere in the file.
I, too, make small commits from a larger uncommitted change, but you don’t need a staging area for that.
Instead of sculpting a staging area and then committing, I sculpt the commit directly.
I usually abort the
git add -p
to modify a file slightly before committing, so I don’t do it in one step. I also like togit diff --staged
before doing the commit, rather than committing and them amending several times to get it right.It sounds like what you like about the staging area is that it gives you a notion of draft/private vs. final/public, is that right?
I use that distinction a bit less, or rather more: instead of one staging area in flux, I feel free to edit any commit that hasn’t been pushed/merged yet.
The draft/public distinction doesn’t require an index/staging area: Mercurial attaches it to commits, instead of to exactly one not-a-commit.
Specifically, Mercurial lets you mark commits as being in phase secret (won’t be pushed/pulled), draft (unpushed), or public (has been pushed/pulled).
[Edit because I submitted too soon:]
As for
git diff --staged
: See how the index concept forces Git to have a separate command? There isgit diff
for the working directory (but staged changes aren’t really in the working dir); andgit log -p
for any commit (but the index is not a real commit), so now you need a third invocation. If you sculpt the latest commit instead of an index,git log -p
can run on HEAD no problem. (And in my daily work I do exactly this, many times per hour.)For me, the difference is typically in when I want to remove some diff from my staged changes. It’s pretty easy to
git reset
the file and redo thegit add
. I’m not aware of a comparable “remove this file from the commit” command, so if I really need to do that, what I have to do is revert the commit, uncommit the revert-commit to get a negative diff of the commit, remove everything but the change I want to remove, then amend the commit with that change.Splitting a commit is indeed a missing feature of git rebase, but git-revise has it, and there is a PR to support specifying paths while doing so (rather than answering yes/no to every hunk).
Before that, I also used to do the double-revert dance.
darcs record
&pijul record
continue amending the current commit in this fashion.unrecord
allows “uncommiting”.Tip: You can
git commit --patch
, just likegit add --patch
. Even with multiple paths if you have. Is that what you mean? It’s not muchgit add
can do thatgit commit
can’t, and it saves a step. Only one thing – committing previously untracked files – which Gogit has now solved.I also use
--amend
a lot, or commit many small commits and then squash the related ones. Or if I have no idea to begin with, I just make one big commit at the end and iteratively split out pieces of it with git revise. Which is just as easy as staging out the same small commit from the same set of unstaged changes, with the benefit that it also works with commits that aren’t the last.I’m aware, but I usually need to
q
thegit add -p
to edit a file, so my workflow isn’t amenable to doinggit commit -p
up front.I don’t find it that big of an issue. Perhaps it is because I learned to do
git status
to orient myself, much like sysadmins habitually typels
like muscle memory.(well, I have
alias gs="git status"
, so it’s not as much typing as you’d think)Most certainly. I never (intentionally) use the staging area, which is why I have no use for git status. Other than to assert that nothing is staged before I commit. I do that if I’m unsure, but it’s not a habit, which is how it surprises me again and again.
The ls thing is a reason that you shouldn’t actually use the command line for managing novel filespaces. It’s only good for filespaces you already roughly know.
If you’re after that, you could try jujutsu