TBH, I feel like a better thing altogether is needed. I never need what pull --rebase does literally (rebase commits from my local branch onto the new state of the corresponding remote branch).
The two operations I actually do are:
make sure that the state of the local branch matches the remote branch exactly (when I pick up my work on a different laptop)
rebase changes in my local feature branch on top of the current state of remote main branch.
I actually use pull --rebase sometimes because, for my personal projects, I’ll switch working between my desktop and my laptop. As an example, sometimes I’ll make a WIP commit on my desktop, pull on the laptop, amend or rebase on the laptop and force push the new commit, then need pull --rebase on my desktop. That’s the only reason I’ve ever needed it, though.
Not sure I understand the use-case. Am I correct that you:
make a WIP commit on desktop
push it
pull it on laptop
do some more work on top (perhaps amending the WIP)
force push the new commit from laptop
and now want to pull from desktop?
If this is it, that that matches first use-case from my comment, and I don’t think rebase actually happens here anywhere? You rather reset your local branch to point to what’s on remote.
I like git config --global pull.ff only, as that will fail the pull and force me to make a decision about what to do if a simple fast-forward is not possible (so when local and remote have diverged).
Squashing is a tool you use to fix WIP commits that you did while developing, then you clean it up to nice properly atomic commits before the final merge. Squashing the entire branch is just a big no.
Squashing entire branches and then merging them, like some projects/people like to do, makes tools like Git bisect and blame awful to use.
Oh very much the same here, sadly. I do try to follow a proper Git model as far as possible, but sometimes I have to revert to the sucky merge flow when a particular branch is just too far gone.
I’ve been trying to teach my coworkers about some of the more “hidden” features of git. In some cases it’s just simple stuff like you don’t have to use git commit -m "<message>" and that you can actually set a visual editor for the git commit editor. Most of them use VSCode so adjusting the git default editor to vscode helps. Then I stopped getting 1 line messages about the change and started to get information that was useful. So instead of just saying in text what the diff says, and started to get the why (which is far more important).
I think everyone agrees that listing out Git branches should probably not be alpha-ordered by default.
The author is wrong on that one. Sorting by default on a field that’s not even part of the listing would be weird. It’s basic Unix aesthetics. ls doesn’t use mtime by default either.
The rationale for this is that when working on branches, the most useful ones tend to be the ones which are most recently used. There are workflows where this is not the case, but it’s reasonable to suggest that these are less common than where it is
And I have an alias for that. But it shouldn’t be the default when the field is not even shown. It would be especially confusing when combined with the multi column display which the author also suggests.
Why not have separate forks per user? The D in DVCS is for distribution, so I would be curious what the purpose of prefixing branch names is as it would only make sense if trying to use Git on a centralized fork.
Yes, this is in the context of pushing and pulling branches from a single central project repo on an enterprise GitHub server. All the work is done there, rather than in personal GitHub style forks. But it’s still very useful to be able to share WIP branches with other engineers.
Why not have separate forks per user? The D in DVCS is for distribution
I wonder if part of this is due to corporate contexts where it might be difficult to ensure that employees who leave the company get their forks of the codebase deleted. Distributed version control is designed around certain non-hierarchical assumptions, but companies are usually fiercely hierarchical.
it might be difficult to ensure that employees who leave the company get their forks of the codebase deleted.
Are you talking about a scenario where an employee checks out their employer’s source code on a personal computer? This is far from the norm, in my experience, even at small companies with otherwise hands-off IT functions.
This one can be rather dangerous. At $WORK, a colleague put this in his global gitconfig, forgot about it and some time later our internal package manager stopped working for him. It turns out that part of our package manager’s configuration is stored in git, and in order to switch between different modes, the package manager created different local references that were wiped by every other invocation. This was quite mystifying as I was completely unable to reproduce. After two hours of debugging over slack I had to just ask him to send me a strace trace and then asked him to gradually remove the files that were read by the package manager and its children until we saw the same behavior. I really wasn’t expecting removing his .gitconfig to solve the problem.
I solved it in the package manager by forcing fetch.prune to false, but I’m traumatized enough that I’ll never use that option in any of my gitconfig files.
But sounds more to me like that package manager is just horribly written and needs to be fixed.
Despite sharing this opinion, I think it’s a bit presumptuous to come to this conclusion without any knowledge of said package manager besides my anecdote.
The Scott Chacon Gitbutler blog posts are consistently great.
I always use git commit -v to write commit messages- it’s in my muscle memory. However, I’m noticing that a lot of people use git commit -m '...', and therefore use an IMHO inferior way of writing commit messages. Just like I recommend everyone teaching Git to newbies to use the “new style” commands (e.g. switch instead of checkout), discouraging the use of git commit -m seems to me one of the better recommendations for newbies.
The “global ignore file” is the other part of this post that I would highlight. It should help reduce many discussions and make your life nicer.
(I’m a big believer that repo gitignore files should be leaner and some of the stuff I find there should be moved to users’ global ignore files.)
Just like I recommend everyone teaching Git to newbies to use the “new style” commands (e.g. switch instead of checkout),
Man, I remember first learning git about a decade ago and being so confused why checkout was so poorly named. It also felt like checkout was being used for everything (change branch, discarding unstaged changes, getting files from a ref, etc).
Newbies these days have it easy… or easier at least :)
I use -m so that the message is saved in my shell history and I don’t have to type it all out again on the occasion that I need to nuke my personal feature branch.
I don’t really get that one… why are you making a commit if you don’t already know what’s staged? Wanting a reminder of what you’re committing after invoking git commit feels odd. Obviously it’s not doing any harm but like I think it would be useless for 99% of the commits I make, where I finished interactively staging the changes in the commit literally seconds before.
Now if in addition to just seeing the diff, you could delete hunks in order to unstage them, I could see that being cool. But I guess at that point you should probably just be using one of the fancy git GUIs or magit or something
Normally, I work for a while, then make a single commit.
Sometimes I make multiple commits in one go, with git add -p. But that’s infrequent.
When I make a single commit, I tend to use git add . (after checking with git status), then git commit -v has two purposes. Doublechecking the diff looks good is not the main one; the main one is composing a complete commit message.
Normally I have a fair idea of what’s in the commit, of course, but being able to review everything helps me not forget anything in the commit message.
having the diff on the screen also helps if you want to mention some technical details that are clearly visible in the diff, e.g. the name of a function that had its behaviour changed and you’re explaining why. in some editors it’s even possible to get autocomplete using all ‘words’ (such as identifiers) in the currently open file, so having the diff on screen can help avoid typos and silly mistakes.
git commit -v is interesting, I do something similar - I use git commit on the command line, my $EDITOR set to vim, and with the tpope/fugitive plugin and autocmd FileType gitcommit silent execute "vert Git diff --cached | wincmd x" in my vimrc to open the diff in a vertical split on the right so I can write my commit message on the left…
Oh, that looks nice. As an Emacs user, I should use Magit (which I expect to do something similar)… but I kinda like to get the “basic” Git experience to be able to give more “entry-level” advice.
As a Windows user I think core.autocrlf=false should become the default. It’s a major pain to work with new people and trying to get everything to work correctly.
It is baffling to me that git will change the content of files as a default. I would expect things to always 100% match the remote.
Mercurial was faced with the same situation about eight years ago. The page FriendlyHGPlan on the developer wiki laid out the game plan nicely:
We’ve been accumulating functionality that the average user probably wants on by default, but can’t always turn on by default due to our compatibility rules. The idea of “Friendly HG” is to give us an opt-in way for users to request our best features as they become polished and ready, even in cases where that violates some of our compatibility rules.
It was implemented as an option called tweakdefaults. Users can put this in their config to opt in to a bunch of quality of life features at once. Because it changes defaults, users can still override individual settings.
My snarky, but truthful git config: brew install jj or mise use -g jj@latest. In ~6 months of using it, I haven’t needed to reach for git a single time. What a pleasure.
Are we, jj users the new Arch user: BTW, I use jj???
git config --global pull.rebase trueIf only this was the default
TBH, I feel like a better thing altogether is needed. I never need what
pull --rebasedoes literally (rebase commits from my local branch onto the new state of the corresponding remote branch).The two operations I actually do are:
I actually use
pull --rebasesometimes because, for my personal projects, I’ll switch working between my desktop and my laptop. As an example, sometimes I’ll make a WIP commit on my desktop, pull on the laptop, amend or rebase on the laptop and force push the new commit, then needpull --rebaseon my desktop. That’s the only reason I’ve ever needed it, though.Not sure I understand the use-case. Am I correct that you:
If this is it, that that matches first use-case from my comment, and I don’t think rebase actually happens here anywhere? You rather reset your local branch to point to what’s on remote.
Yeah, you’re right my bad, it’s too early for me 🤦♂️
I like
git config --global pull.ff only, as that will fail the pull and force me to make a decision about what to do if a simple fast-forward is not possible (so when local and remote have diverged).Abandon all hope. Let the merge commit exist and just squash your branch when it’s time to merge it back.
I will never accept squashing on that level.
Squashing is a tool you use to fix WIP commits that you did while developing, then you clean it up to nice properly atomic commits before the final merge. Squashing the entire branch is just a big no.
Squashing entire branches and then merging them, like some projects/people like to do, makes tools like Git bisect and blame awful to use.
My workplace is very dysfunctional when it comes to
git.Oh very much the same here, sadly. I do try to follow a proper Git model as far as possible, but sometimes I have to revert to the sucky merge flow when a particular branch is just too far gone.
I’ve been trying to teach my coworkers about some of the more “hidden” features of git. In some cases it’s just simple stuff like you don’t have to use
git commit -m "<message>"and that you can actually set a visual editor for the git commit editor. Most of them use VSCode so adjusting the git default editor to vscode helps. Then I stopped getting 1 line messages about the change and started to get information that was useful. So instead of just saying in text what the diff says, and started to get the why (which is far more important).It’s useful working on a team where we use
username/topicfor our branch names. Then each of us has our working branches grouped together.The author is wrong on that one. Sorting by default on a field that’s not even part of the listing would be weird. It’s basic Unix aesthetics.
lsdoesn’t use mtime by default either.The rationale for this is that when working on branches, the most useful ones tend to be the ones which are most recently used. There are workflows where this is not the case, but it’s reasonable to suggest that these are less common than where it is
when listing out directories it is also very useful to order by date modified.
in fact, my Downloads folder is almost always configured to do this; its default in MacOS at least.
And I have an alias for that. But it shouldn’t be the default when the field is not even shown. It would be especially confusing when combined with the multi column display which the author also suggests.
Why not have separate forks per user? The D in DVCS is for distribution, so I would be curious what the purpose of prefixing branch names is as it would only make sense if trying to use Git on a centralized fork.
Yes, this is in the context of pushing and pulling branches from a single central project repo on an enterprise GitHub server. All the work is done there, rather than in personal GitHub style forks. But it’s still very useful to be able to share WIP branches with other engineers.
It makes it easier to pull someone else’s branch (needed all the time for code review) and to push to someone else’s branch (needed once in a while).
With using forks, you would have to add a bunch of remotes manually every time you clone a repo, which is a lot of manual work.
Also CI-related things are typically easier when centralized.
I wonder if part of this is due to corporate contexts where it might be difficult to ensure that employees who leave the company get their forks of the codebase deleted. Distributed version control is designed around certain non-hierarchical assumptions, but companies are usually fiercely hierarchical.
Are you talking about a scenario where an employee checks out their employer’s source code on a personal computer? This is far from the norm, in my experience, even at small companies with otherwise hands-off IT functions.
This one can be rather dangerous. At $WORK, a colleague put this in his global gitconfig, forgot about it and some time later our internal package manager stopped working for him. It turns out that part of our package manager’s configuration is stored in git, and in order to switch between different modes, the package manager created different local references that were wiped by every other invocation. This was quite mystifying as I was completely unable to reproduce. After two hours of debugging over slack I had to just ask him to send me a strace trace and then asked him to gradually remove the files that were read by the package manager and its children until we saw the same behavior. I really wasn’t expecting removing his .gitconfig to solve the problem.
I solved it in the package manager by forcing fetch.prune to false, but I’m traumatized enough that I’ll never use that option in any of my gitconfig files.
fetch.pruneis safe, that only removes remote-tracking branches, not local ones.fetch.pruneTagsdoes remove all local tags that are not on the remote though. The Git documentation does have a warning about it: https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt---prune-tagsBut sounds more to me like that package manager is just horribly written and needs to be fixed.
According to https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt---prune , –prune will delete tags too, and so would not be safe.
Despite sharing this opinion, I think it’s a bit presumptuous to come to this conclusion without any knowledge of said package manager besides my anecdote.
Am I wrong, or was this option previously made a default in https://github.com/git/git/commit/5404c116aa921d7e2f9408e103c80b7801735d08?
The Scott Chacon Gitbutler blog posts are consistently great.
I always use
git commit -vto write commit messages- it’s in my muscle memory. However, I’m noticing that a lot of people usegit commit -m '...', and therefore use an IMHO inferior way of writing commit messages. Just like I recommend everyone teaching Git to newbies to use the “new style” commands (e.g.switchinstead ofcheckout), discouraging the use ofgit commit -mseems to me one of the better recommendations for newbies.The “global ignore file” is the other part of this post that I would highlight. It should help reduce many discussions and make your life nicer.
(I’m a big believer that repo gitignore files should be leaner and some of the stuff I find there should be moved to users’ global ignore files.)
edit: well, started yet another small advice text on my personal repo.
Man, I remember first learning git about a decade ago and being so confused why
checkoutwas so poorly named. It also felt likecheckoutwas being used for everything (change branch, discarding unstaged changes, getting files from a ref, etc).Newbies these days have it easy… or easier at least :)
I use -m so that the message is saved in my shell history and I don’t have to type it all out again on the occasion that I need to nuke my personal feature branch.
You can rescue old commit messages from the reflog
I’m sure, but that sounds a lot more complicated than typing:
git co<Up>I don’t really get that one… why are you making a commit if you don’t already know what’s staged? Wanting a reminder of what you’re committing after invoking
git commitfeels odd. Obviously it’s not doing any harm but like I think it would be useless for 99% of the commits I make, where I finished interactively staging the changes in the commit literally seconds before.Now if in addition to just seeing the diff, you could delete hunks in order to unstage them, I could see that being cool. But I guess at that point you should probably just be using one of the fancy git GUIs or magit or something
Normally, I work for a while, then make a single commit.
Sometimes I make multiple commits in one go, with
git add -p. But that’s infrequent.When I make a single commit, I tend to use
git add .(after checking withgit status), thengit commit -vhas two purposes. Doublechecking the diff looks good is not the main one; the main one is composing a complete commit message.Normally I have a fair idea of what’s in the commit, of course, but being able to review everything helps me not forget anything in the commit message.
having the diff on the screen also helps if you want to mention some technical details that are clearly visible in the diff, e.g. the name of a function that had its behaviour changed and you’re explaining why. in some editors it’s even possible to get autocomplete using all ‘words’ (such as identifiers) in the currently open file, so having the diff on screen can help avoid typos and silly mistakes.
git commit -vis interesting, I do something similar - I usegit commiton the command line, my $EDITOR set to vim, and with the tpope/fugitive plugin andautocmd FileType gitcommit silent execute "vert Git diff --cached | wincmd x"in my vimrc to open the diff in a vertical split on the right so I can write my commit message on the left…Oh, that looks nice. As an Emacs user, I should use Magit (which I expect to do something similar)… but I kinda like to get the “basic” Git experience to be able to give more “entry-level” advice.
Magit does exactly that by default (split, and show commit buffer and diff side by side)
I like to use
git guifor writing commit messages… I find it nice to be able to scroll through the individual files I changedAs a Windows user I think
core.autocrlf=falseshould become the default. It’s a major pain to work with new people and trying to get everything to work correctly.It is baffling to me that git will change the content of files as a default. I would expect things to always 100% match the remote.
Mercurial was faced with the same situation about eight years ago. The page FriendlyHGPlan on the developer wiki laid out the game plan nicely:
It was implemented as an option called
tweakdefaults. Users can put this in their config to opt in to a bunch of quality of life features at once. Because it changes defaults, users can still override individual settings.My snarky, but truthful git config:
brew install jjormise use -g jj@latest. In ~6 months of using it, I haven’t needed to reach for git a single time. What a pleasure.Are we,
jjusers the new Arch user: BTW, I usejj???