- Always pull w/ rebase for the current branch.
- Always merge other branches into your current branch, eg master -> feature.
- Always stage individual chunks of code one at a time to make sure I'm committing the right stuff.
- Always squash feature branches into a single commit when merging back.
- Stash changes if needed when switching branches.
- Cherry-pick one-off commits if needed.
- Append a previous commit that I haven't pushed yet if I happened to forget something.
- For complicated merge conflicts I switch to Visual Studio Code which also has a great GUI.
I think this covers 99% of the stuff I encounter in my day-to-day.
This is really the only command I do by hand because I can't find the equivalent (yet, probably haven't looked hard enough) in Fork.
edit: oh I think I misread what you said. When working on a feature branch I don't care too much about the branch history since I know it's eventually being squashed back into a single commit.
Anything works when both of those prerequisites are met. You're unlikely to do the bad things that force more advanced needs.
Everyone should do this. Think back to how much time you've lost due to git problems. It'd probably take less time to learn it correctly up-front, and never have to deal with them ever again.
It seems to have next to zero functionality. What is the point of it? What you you use it for, other than commit, push?
Find a _simple_ git workflow, document it in a style guide, stick to it. Git doesn't have to be complicated.
I also don't bother appending (though my GUI lets me undo the last commit if I haven't pushed which is maybe the same thing.)
Most developers get way too fancy with Git and screw something up. I use GitHub Desktop and rarely touch the command line for Git. It has a great UI for being able to just pop over and see my current changes, and easily commit just a line or two from them to make commits other people can understand.
I don't know why, but I've always felt uncomfortable using git in a GUI, but I know a lot of people who love it.
For some reason, anytime I try to use a GUI, I don't feel like I'm really doing git, if that makes any sense. Also, I've personally never felt the need to see the branches visually. And if I do get the itch to 'see' them, nothing a quick
git log --oneline --graph
cant fix!* I almost always just do a regular merge to master (rather than squash).
* I use GitKraken which (in the pro version) has a great merge tool.
A lot of people seem to want "clean history" so just I'd just like to put it out there that it's not really necessary (there's nothing wrong with it, of course), and regular merges work just fine. In my experience, the two main reasons I look at git history are:
(1) Checking when a feature was done and what releases it got into
(2) Finding out why a particular line of code exists (blame)
For (1), with software with numbered releases, you end up following the branches anyway. Having the individual commits from feature branches makes you scroll more, but it doesn't make it any harder to follow. If you really don't like seeing them, you can hide anything but merge commits.
Even simpler, if all you care about is whether a given feature branch is done (merged) or not, that's easy to see and the same as a squash-merge workflow.
With continuously-deployed ("cloud") services, things are even simpler - you start at the hash currently deployed and go backwards. It makes no difference if there's one branch or many feature branches (other than scrolling past more granularity).
For (2), the greater granularity from individual commits is generally useful (at least provided that each commit has a ticket number and useful description), and squashing erases this detail.
Also, a nice thing is if you end up merging the same branch to multiple places (master and a release branch, for example) it's obvious what happened by looking at the tree. Contrast to if you cherry pick a squash merge commit, the only way to see that is to read both commits and realize they're the same -- and this is much less obvious if there's other commits between them.
Basically, squash merging doesn't help with either of these, and in fact actively hinders (2).
My team has been doing this for a few years, and I'm not even sure if it was a conscious decision to merge this way (or not do squash merge) but we've had no reason to change. It does depend on every commit being well-formed, but this is pretty easy to ensure in a paid team that works on this every day (whereas with open source I'm not sure it'd work well).
Anyway, like many things in git, there's more than one way to do it, and there's no clear "right" or "wrong" way.
git add/rm/commit/status/push
git branch/checkout/merge/rebase
git tag/push --tag
Anything else should be handled by policies. If you get bad PR, reject it instead of trying to fix it using some complex sequence of git commands.You also need `git log` with all sorts of arcane options if you actually want to use the history.
Stash can be useful, but it’s good to know that you can get by without it very easily, there’s nothing you can do with stash that you can’t do with commits & branches, and stash doesn’t have the same safety mechanisms that commits have. I think the biggest git accidents I’ve seen, where people have gotten confused in the middle of a merge and lost their work, are due to using stash.
That's probably anathema to some users, though.
I _really_ love working with Git, but in my experience engineers unfortunately do need to tap into the long tail of “advanced” commands fairly often. At least often enough that they will quickly be frustrated by it.
(I’m currently helping move a bunch of our engineers from SVN to Git, and while I believe the better ecosystem will be worth it, it does break my heart every time someone has pointless trouble simply because of Git’s CLI.)
Reclone from master (or the active branch if something else) to another directory, merge in their final changes, manually if needed, properly test the result, and sent a new PR with the cleaned up version?
(caveat: I've not used git in anger, there may be more to it than that, but I can't imagine much more)
I suppose who is responsible for dealing with cleaning up updates before merging them into the main project depends upon who wants it merged most: the PR submitter because they want a fix/change/other in upstream so they don't have to maintain their own fork, or the project maintainer because the update is more generally useful to other users or more specifically useful to the maintainer.
If you submit a badly arranged PR or other patch you are creating extra work for the project maintainer(s). Depending on the project and maintainer(s) this may be acceptable or, equally rightly, it may not.
My own list contains:
ssh user@rsync.net "git clone git://github.com/LabAdvComp/UDR.git github/udr"
... which is how I make my own copy (in the cloud) of (what I consider to be) important packages that I want my own archive of. git guiFor example build and test all commits but deploy only if it's on master branch AND has a version tag.
I know without hesitation all commands I use daily. And then I keep a note with the few commands I use less often. An exception is when I want to display changes between version, or conflict resolution.
That being said, I'd like to rely just on my IDE (VSCode) for better consistency, and I tried a few times, but I always return to the command line which is a great tool. For the same reason, I prefer to `CMD-tab` to terminal and `make` rather than build from the IDE.
this is emacs we are talking about :) you are supposed to use the keyboard for everything.
https://github.com/hlissner/doom-emacs
In magit in those Emacs distributions, the question mark brings up a list of available commands and if you type the first letter of a command with multiple letters, it'll show you the names of the actions that start with that key.
I was happy with the git cli (and occasional tig) when I started using magit full time and initially never understood all the buzz. It did not seem that powerful over what I was using.
After 3-6 months of use, for some reason I had to go back to the cli and then I realized the ease and speed I had got accustomed to.
Magit is magical; use it for some time and try going back to your previous setup.
[0] https://github.com/tpope/vim-fugitiveIn which cases you found it "opens" git for deeper inspection?
My experience is that it lets me operate at higher levels of abstraction than cli git. (e.g. Instant Fixup)
#!/usr/bin/env bash
emacsclient -c --eval "(progn (magit-status) (delete-other-windows))"
The learning curve is a bit long, but really worth it!Note: this require you to have setup emacs as a deamon somehow
One of the things I appreciate about magit is that it gives you sane default behaviour. For instance, the -f option when pushing with magit is —force-with-lease, rather than —force, so that you don’t inadvertently overwrite someone else’s work. When stashing, it helpfully prompts by default you to enter a message for your stash to differentiate it from the 10 other stashes you might have on a branch. Sure, these are things you can get on the command line, but they’re not the defaults, and you have to remember how to get to them.
I only have emacs open for magit (:
I'd also be interested to hear what git commands others use frequently (that don't involve a GUI). I'm curious to know which workloads might require some of git's more advanced features on a regular basis.
git diff --color-moved
(seriously, read through the man page for git diff sometime)
git log -p --all -- <path/to/file>
(I use this with multiple remotes, so I can track changes in my fork and in upstream when looking for context around a file)
git cherry-pick -x
(for automatically adding a reference to the original commit)
A couple more, but I think they're really quite specific to my personal workflow and responsibilities
I agree about `git log -p`. A good trick with that is to use it as a quick way to search for a commit that includes a certain string (since the pager is less, one can search back in time with `/`).
Same trick for `git reflog -p`.
`git stash show -p` is another less-known diff command (look at a stash without applying it).
I like this one. I'll remember it. Thanks for sharing!
Have you read through the gittutorial, gittutorial-2, and especially the gitcore-tutorial manpages[1]? Reading those guides and actually following the steps and examining the results on disk was extremely helpful for me in understanding how Git actually works. Once you've got that understanding, the Git UI seems less arbitrary. You can start to see how it was put together over the years, which should help you use the tool more intuitively and effectively.
> I'm curious to know which workloads might require some of git's more advanced features on a regular basis.
I work on a very large and very old (mid-90s) project, so history-diving and diffing branches is very useful for me. I use all of git-blame, git-show, and git-diff to examine history to learn how the code came to be as it is. Even git-cat-file comes up occasionally when I just want to look at some old object I happen to have a hash for and don't want to look up properly through the porcelain.
We also maintain a bunch of branches and backport modern commits onto legacy branches. git-rebase can help for this, but more often I find myself doing it manually (well, with a bash script) with git-cherry-pick, as it's easier to work with commits without being in the middle of a rebase operation. Knowing git-log's many options to massage history into a useful form for my work comes in very handy here, too.
More details on the rebasing procedure I use: https://github.com/ValveSoftware/Proton/blob/proton_4.11/doc...
Here's some of the tooling I use often. For Git stuff, see pick_commits and gitconfig https://gitlab.com/mywinetools/mywinetools/
[1] I know, I know, no one likes studying and learning how to use a tool. But sometimes you gotta if you want to use the tool effectively.
Wow, mid 90s! Git came out in 2005, so I assume they started out using some previous version control and then switched to git? That must lead to some serious knots. Is there a way to retroactively migrate source control history into git? Depends on the legacy source control tool, I guess.
I think git-blame and git-cat-file are probably the next commands I need to explore in depth. Will investigate those further.
Thanks for sharing your gitconfig as well. Always interesting to see how others are streamlining their workday.
https://www.git-scm.com/docs/git-log#Documentation/git-log.t...
Right now, Im partial to Sublime Merge[0] as it’s fast, has a clean UI for diffing, shares many similarities with Sublime, and also shows the use what git commands they’re running by hovering. It can be a very effective tool for learning git. It has the same evaluation structure as Sublime, so that’s a bonus as well.
But I can’t bring myself to run a web browser to run git commands either. The git binary on my system comes out at 2.5Mb and the MacOS .app bundle for this is 346.5Mb.
When the conflict occurs you can do git status and the highlighted files are those with a conflict -- at that point you can just navigate there in the code editor of your choice and look for the <<<< blocks. After you get those files into the state you would like then you run 'git commit' to resolve.
Love seeing high-quality software developed by just 2 people.
[alias]
# top 10
top = !sh -c 'git log --oneline|head -10'
It shows the top 10 commits. I use it several times every day, to orient myself while flipping between multiple repositories and branches.Also known as a porcelain, as opposed to the low-level commands known as the plumbing.
Basically, you can do a working copy of the git environment without pulling the repo again, so you have only one .git folder.
A godsend if you, like me, work on gigantic repos that build unbearably slowly and want to be able to use multiple instances of the same repo at the same time.
After `make clean` and `git status --ignored` shows nothing worth preserving, you can delete the worktree (via `git worktree remove`) with impunity. No more paranoid checking that there is no valuable work stashed or hiding in other branches before typing `rm -rf`, as those are shared with the main worktree so won't be lost.
Committing, pushing, handling local branches, updating, merging, rebasing, cherry-picking, squashing and stashing is almost all that everyone uses, and several of those not even on a daily basis.
$ git reset --hard origin/master
over the suggested
$ git reset --hard HEAD
If you use git and don't know the difference, read this: https://stackoverflow.com/questions/8196544/what-are-the-git...
branch checkout add commit pull push
Reading and understanding the documentation for those six core commands isn't a big investment, and it will pay off if you're doing software or documentation development.
Then I met sublime-merge. And fell in love. It is the only Gui I find more efficient and beautiful than my terminal. I highly reccomend it.
http://www.philandstuff.com/2014/02/09/git-pickaxe.html
Also I do allot of
git reset --soft HEAD;
(pick-hunks-with-GUI);
git stash -u -k;
run-test.sh;
git commit -m "blah"`
(i.e. that this is necessary speaks volumes)