> Using git can be daunting at first. Like my good friend Chris once said, "everyone knows the happy path but the minute it gets hairy we're all screwed".
Sounds familiar. Lots of people just learn a few template use-cases, but don’t take the time to learn/study the tool. You might argue you shouldn’t need to but Git isn’t intuitive and does require investment. It comes with its own terminology; there’s no point just guessing what a branch is for e.g..
Like all powerful *nix cli tools, if you don’t you’ll shoot yourself in the foot one day. Even if you want to use a GUI interface, it’s no substitute for learning how git works behind the scenes.
Sometimes when I offer to help a colleague that’s got themselves into knots the sad thing is often they can’t even explain the problem they got into.
> We therefore squash and merge our feature branches onto dev when a PR is opened and merged. Regardless of how many commits a feature branch has, once it is merged, all the commits are squashed into a single commit
So several steps to implement a feature are mixed up into a single change :/ That looks awful to me, when you need to read the history to understand how and why.
I would strongly encourage getting rid of the dev branch. It is redundant in almost all cases.
Instead think of the master branch as the integration branch. This is where everything gets merged ready for a new release. But the master branch itself is not a release. You can automatically deploy the master branch to a staging or "next" environment if you wish.
For releases, use tags. That's what they are for. If necessary you can make one or more "maint" branches where you backport important fixes from the master branch on to release branches to create patch level release versions.
Sorry, but no, a branching workflow won't scale if you have thousands of developers pushing to the same repo. Those pretty `git log --all --decorate --oneline --graph` images won't work when you've got thousands of branches, and the history on the mainline will be poor and of low utility.
What I was taught almost 20 years ago at Sun Microsystems (RIP) is a rebase workflow. That was back before Git. We were using Teamware of all things, and we were using it with a clean, linear upstream history workflow.
Our particular rules were:
- linear history upstream
- absolutely no merge commits (at Sun
they were called "merge turds")
- one commit per-bugfix, though one
commit could fix more than one bug,
with a separate commit for test
changes
- one commit per-project
- but otherwise one push could push
many commits
We also had rules about commit titling, naturally.Sun had been using that workflow since 1992 as I recall, so they used that workflow for 16 years, with several thousand developers pushing to OS/Net (core of Solaris).
We even had rebase --onto.
The workflow for projects went like this:
- devs push to a project clone of the upstream
- gatekeeper takes care of build issues and
preps to push to upstream when project is ready
- every so often the project repo ("gate") would
rebase onto the upstream head, then devs would
rebase their clones onto the new project head
- eventually the project would rebase onto and
push to the upstream
- project repos ("gates") got archived when the
projects completed
That workflow scales very very well. The resulting upstream's history is very clean, with just: commits for bug fixes, commits for tests for bug fixes, commits for projects, commits for release-making, and the occasional follow-up to a commit that fixed minor issues with that commit (e.g., `12345 Crash in blah blah (fix style)`).I strongly recommend it.
Man, I really feel for people who struggle with Git. I should know - I was one of them many years ago.
Many day-to-day problems with Git all have something in common which is that the user has got their repo in to some state they do not understand. And most times (as comments have mentioned) they don't even know what they did to get themselves in their current pickle.
The quickest path to resolution is usually a hard reset to the server version of the branch then restore the commit(s) that user had made.
If you have pending changes then handle those first. It doesn't matter much what they are just commit or stash. If committing don't even think about the message just use `wip commit`. Finally, note every commit id that has your work you want to keep around. Might be 1, 5 or 20 commits.
Okay, now hard reset.
`git reset --hard <remote_name>/<branch_name>`
Great, now you're at an acceptable state.
Finally, restore your previous commits use cherry-pick or `git stash apply` to get your stuff modified.
If cherry pick then it's `git cherry-pick <sha_oldest> <sha_next_oldest> ....`
On to the next problem...
> As of git 2.11 one can select a specific stash to be popped instead of just the latest stash using git stash apply n where n is the stash number.
You can pop or just apply a specific stash using
git stash { pop | apply } stash@{N}
This has worked as far as I remember; I have a 1.6 installation somewhere where I can confirm it, if necessary.Those commit messages leaves a lot to be desired.
"Changes print messages again"
How helpful is that? In what way were they changed? What was the intention behind the change? Is there a ticket or a feature request behind it? Why was that particular change chosen instead of all the other ways to achieve the same effect?
It's also considered prudent to keep to a common format. These are even written in differing tense, where imperative is by far the most commonly preferred.
Using dev and master branches is anti pattern and does not scale. Soon your QA team wants a QA branch. Then business wants a branch for demos. The DevOps ... Etc. Use tags. You only need one branch called "main". The way open source projects do it is best, look no further!
My favorite git-related thing is `diff2html` so I set up an alias `diff` which will open the browser and show me all the changes I've made to the branch:
could someone tell me which is the git UI client shown in the screenshots of the blog post? https://riskledger-website-media-uploads.s3-eu-west-1.amazon...
I never touch the git rebase at once in my 10 years of programming. It's born to solve a problem little people face ? I'm not sure though.
I’m surprised so many organizations use the term “master” for the primary branch instead of the more inclusive “main”.
I feel that having a default merge strategy to squash and merge all commits in a branch is a version control anti-pattern. This discourages thoughtful and frequent commits that express the intent of a change because all the commits are just smashed together anyway so why bother. I think context and intent is lost when looking through git history of large smashed commits.
I prefer using a precommit hook to automatically prepend a Jira ticket number to each commit so when you look at the history you'll see multiple commits grouped together with the same ticket prefix, but the commits still retain the intention of the commit. Knowing that commits will not be squashed promotes devs to make meaningful commits. I still advocate for cleaning up and squashing your own commits as you see fit with an interactive rebase before your branch is merged. Having discrete commits can also help when running git bisect to find when a bug was introduced so you identify the specific commit instead of a feature being merged.