October 22, 2018

The GIT version control system - day to day use

Once you have a project set up, you typically find yourself editing one or more files and getting to a place where you feel satisfied with what you have done. Either that or you have done so much work you feel nervous about having only one copy. Either way, you want to put your latest changes under version control.

You can type "git status" at any time, and I use it a lot to find out what the state of things is. It tells me what files are staged to commit and whether I need to push things to my remote repository.

The following will put the changes into the local repository AND push them to the remote repository. You typically only do both when you reach a significant milestone and everything is tested and working.

git commit -a -m "fiddled with stuff"
git push origin master
I usually don't put the "-m message" on the command line and let git prompt me for the commit message. I also leave the "-a" off and precede the "git commit" with "git add .". So my usual set of commands is:
git add .
git status
git commit
git push origin master
Doing the status before the commit lets you see what the add has staged for commit and prevents you from commiting a bunch of binary files and the subsequent cursing and need to edit the .gitignore file and clean up the mess.

Status commands

I use "git status" all the time. Two other commands can provide more in depth information.
git diff
git log
The "log" command gives you a history of what has been commited, which will be only as useful as the commit messages you gave when you did the commit. In a big collaborative project, there are often strict policies about making quality commit messages and how they should be formatted.

Pulling changes from the repository

You will need to do this if you are collaborating with someone and they have pushed new changes. You may also need to do this if you have been working at home and pushed new changes, then have driven to work and want to pull those changes into your working copy on the machine at work (or the reverse). Or perhaps you cloned some public project and want to bring your working copy up to date with the latest changes.
git pull
Or this:
git fetch origin
git merge origin/master
At this stage, I always do "git pull", but there are fine points here that are important if you are doing more advanced things with git.

The fetch pulls all data that you do not yet have in your local repository. The command "git fetch origin" is what you use to keep a cloned project up to date. It only updates the local repository though, not your working files, you need to merge to do that. Git pull will try to fetch and merge both.

See this article:

I read an essay somewhere that said mean and nasty things about using git pull and said you should always fetch and merge. As near as I can tell, this is only important if are working with branches and changes have appeared that do not pertain to your branch. In such a case, the changes would not be automatically merged and you would be given more control about how things would be handled. For most of what I do, this is just needless hassle.

Staging area and index

You may not actually need to know this, but here goes anyway. Git considers each file to be in one of the following states: Git uses a single file (called either the index or staging area) to keep track of which files will go into the next commit. Some people get worked up about the index in one way or another. I consider getting a solid grasp of this a more advanced git topic and beyond what I want to deal with in this tutorial. Using "git status" frequently and getting comfortable with what it shows you is a great start to understanding this. (Or maybe the reverse is true, understanding the staging area may help you to understand the cryptic output from "git status"). My tip is to use "git status" and pay attention.

Going beyond endless commits

For me, much of using git is a sort of "backup scheme". If I commit frequently, then screw up some file, I can always retrieve the last version I commited from the repository. To revert to some prior version:
rm file.c
(or better yet, mv file.c file_BAK.c)
git checkout file.c
Note that "git checkout" can be used at any time to pull a specific file out of the repository.

To get rid of a file (to make git stop wanting to track it, and to actually delete the working copy too). If you just delete the file, git will notice and complain and do its best to restore it for you. Nothing actually gets deleted till you commit though.

git rm file
git commit
To rename a file, do this:
git mv old new
Git is smart enough to notice if you just do a rename, so you can just do the rename and let git do clever things, but I feel better telling it.

Tags

There are two flavors: lightweight and annotated. A lightweight tag is just a pointer to a specific commit. Annotated tags have dates, email address and taggers name, a message, and a GPG signature.
git tag
git tag -a v2.03 -m "My version 2.03"
git show v2.03
If you omit the -a and -m you get a lightweight tag.

Tags must get pushed explicitly to a remote server:

git push origin v2.03

Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org