Git source control is somewhere behind most of the software we work on today. It has a bit of a reputation for being difficult to use.
Depending on your workflow, you may not realize just how lazy git is, and that could cause you headaches.
Distributed Development is Lazy
Git supports distributed development. Unlike centralized version control which usually locks files when a developer is changing them, multiple people can make changes at the same time, and the "central" server is a choice, not a requirement.
It also lets you maintain multiple branches and multiple remote sources, and those sources don't have to be in sync. The Linux kernel, for which git was developed, uses layers of servers to accumulate changes.
With git, your remotes don't even have to be servers. And git doesn't assume it can communicate with the server. It doesn't even assume you have a network connection!
Because of this, Git won't do anything you don't tell it to. In our heavily connected modern world, the idea of a tool that doesn't ever check in without you telling it to can seem out of place. It can even cause headaches for developers, so it is important to remember.
Adding Remotes - Seriously Lazy
The clearest demonstration of git's laziness is adding a new remote. If you have forked a public project, you would clone your fork and it would be listed as origin
by default. If you wanted to pull work from the original project, you can add an upstream
remote.
git remote add upstream git@github.com:some/repo.git
If you use a tool or integration for git, it might mask this, but if you don't you'll discover you can't check out anything from the remote until you run another command:
git fetch upstream
In fact, you can provide completely invalid information when you create a remote without generating any errors, ever.
git remote add whoops htp:/mistake
If you don't fetch from that remote, it will be like it doesn't exist.
Checking Out Branches - Subtly Lazy
This is where headaches can come from. When you go to check out a branch from a remote, you might assume it's up-to-date.
git checkout --track origin/my-feature
And git may even tell you it's up-to-date. But it's only as updated to your last fetch! If you haven't fetched code in a while, your clone of the repo may be stale.
File Updates - Somewhat Lazy
When you make a change to an existing file, git will recognize that file has changes. Certain commands will automatically capture changed files, but will not capture new files. The documentation for git commit -a
communicates that it is specifically for modified or deleted files.
git commit -am 'Commit only modified (including deleted) files'
Moving Files - Uniquely Lazy
Git can detect moved or renamed files, and git mv
can help with it, but if you modify the file after a move without committing it first, git usually thinks you deleted one file and created another.
This might not seem too important, until you realize that all of the git history from before the move is no longer associated with the moved file, which can make it difficult to trace changes across history.
Moved or renamed files should be committed before any other changes.
Lazy Isn't Bad
This article might sound like git needs to be fixed, but the focus is on understanding our tools.
- Adding remotes without confirmation still works without an internet connection, or while the server is down.
- We can always start a new branch without waiting for syncing, so we can focus on code now and deal with merges or rebases at another time.
- We don't have to worry that temporary test output files will be committed because new files are not added automatically.
Conclusion
Git is a powerful and complicated tool with many capabilities we will rarely use. Understanding a bit more about how it works can remove the confusion and frustration. And don't forget to read the manual when you get stuck.
Do you have a different way of thinking about git, or tips for how to make sure avoid mistakes? I'd love to hear about them!
Top comments (0)