Git Basics
As mentioned previously, I'm going to cover a bit of how I use git on a daily basis. This won't be exhaustive and I hardly believe it's the "best" way to do anything, but it's how I use it.
The first thing to mention, and something I use often just to see where I'm at, is git status
. This returns any active changes you may have on the branch. Speaking of, I very commonly make branches for my work. This is almost a duh for most, but I think the tip I want to add here is to prefix your branches with your name/username to help organize them even further. When working with even a few people, having your names on branches (i.e. "yudjinn/added-cool-feature") really helps keep branches going crazy. I tend to do it all in checkout
: git checkout -b yudjinn/feature-added
.
Something you'll see frequently in tutorials, but I think is a bad practice, is git add .
. This is because you should be deliberate about what is getting staged for commits. I'm not saying it doesn't have its place, but having a habit of staging *everythingm quickly can cause issues. The most obvious is that accidentally adding temp files or dev-specific files (say, environment files for your database connection, as an example), which can be a pain to hunt down and remove from the git history. The other, maybe less obvious reason is you can really give meaning to your commit messages. Say you're working in a web backend setup as an MVC (model-view-controller). If you ended up updating an endpoint to add a cool new feature, you'd likely have changes in your view/controller modules. But say in doing so, it also became apparent you needed to pass api-keys in a more sane way for this to work. Now this is related, but not the same work. It makes more sense to add your api-key work to a commit, adding a message describing the change and need, then add the view/controller changes to a commit with a message more scoped to the funtionality. This is a bit of a contrived example, but it should be easy to see how separating these changes can help for maintainability, and if something broke, it's very easy to go back and see what it is. Nothing is worse than a commit with 40 changed files saying "updating stuff" that you're positive broke your CI/CD pipelines.
Next is something that is a little more obscure (at least in my experience): submodules
. Git submodules are super powerful and really help maintain multiple projects that are dependent on each other. Some people take the monolith approach: "I have a backend and a frontend that talk to each other and I want them shipped as a single app. Therefore, this should be one big repository with folders for each sub-application, which may be in different languages and have different dependencies." I hate that sentiment. Here's the saner approach: having a coordination repo that submodules in the frontend and backend applications and does deployment-specific things if needed. This means you have a repository for each the frontend and backend, and you can easily setup pipelines and do development on them without worry about breaking the backend somehow. You can do the same for the backend. Even better, if you add a new page to the frontend, but the backend application hasn't been updated to provide the endpoints yet, you can just leave the commit hash in the coordination repo the same until it's available. This means your updates are more deliberate and you can validate the whole system will work together BEFORE pushing to master. Submodules especially useful if you have a library you want to use in a bunch of projects, but don't want those projects to have the ability (or responsibility) to update and change the library.
Last thing is interactive rebase (git rebase --interactive HASH
). This pops up a list of all commits you have since the commit HASH provided. This is super useful if you're iterating on, say, a config file and it took you 6 or 7 tries to get it right. Some may use the git commit --ammend
to just overwrite the commit as they go, but if you dont, you can just have the interactive rebase squash those 7 commits into one. If you have a commit you didnt even mean to have there (from a cherry-pick or a git merge origin/master
), you can also drop those commits. Or if you're a derp like me and added the wrong files to a commit and want to fix them, you can also edit your commit. From there, upon closing the file, it will take you step-by-step through your rebase, allowing you to really coordinate your branch changes before submitting a pull request.
Pet Peeves
This is a fun little section for things that tend to get on my nerves, but I think there is still value to saying them:
The first is dont EVER force push over a branch that isn't yours unless you have already talked to the owner and they know you're going to. I've had to redo too much work because of someone overwriting my commits with theirs.
Next is extremely vague commit messages. Don't tell me "updated stuff", say "updated lib to 2.4". Don't say "fixed UI", say "fixed bug causing button on page to not function". It's not hard and it gives context to anyone reviewing your pull request.
Use
git rebase origin/main
, notgit merge origin main
. I don't want to go super into why, but suffice it to say rebase places your work AFTER themain
's tip, while merge shuffles them together. This is just rife with merge conflicts and is a quick way to cause accidental reverts of code. Can't tell you how frustrating it is when you fix a bug and a week later, it's back. Luckily, it's usually trivial to reapply your fix, but it's just making more work for no benefit.Before
commit
ting, double check what branch you're on withgit status
orgit show
. It can be a pain if you don't catch it quickly when you commit to an old branch that has drifted far behindmain
.
Alright, enough of my soapboxing. I hope a couple of these tips are useful to you. I have a few more that are more intened for large repositories, but that may be best suited to its own post.