elf-notes/content/git/_index.md

5.5 KiB

+++ title = "Git Notes" description = "Basic documentation of Git" date = 2022-04-27T18:00:00+00:00 updated = 2022-04-27T18:00:00+00:00 template = "section.html" sort_by = "weight" weight = 6 draft = false [taxonomies] documentation=["Reference"] categories=["Git", "Version Control", "VCS"] +++

Git is the most widely used version control system (or source configuration management) tool. Pretty much everything I do uses Git. This is where I keep my notes on how to do things.

Starting a project

Git is project and folder-centered, and to start using git go to the root folder of a project you want to place under source control and initialize it:

$ mkdir a-new-project
$ touch README.md
$ git init

This creates a new folder, .git, where Git will store your commit history and some configuration details. Git will usually not create a repository without something to store in it, but see the git start alias below.

Putting files into git

To put files under source control, you must add them. To update the entire folder, switch to the root of the project and add all of it:

$ git add .
$ git commit

An editor will pop-up, asking you what this commit is about. It's generally polite, especially if you're working in a team, to explain your commit in some detail-- and to generally keep the commit small, in order to ensure that you don't have to explain too much!

If your commit message could be a single line, you can add it directly from the command line:

$ git add .
$ git commit -m "Updated the widget to widgetize."

... and you can even combine both commands, but be careful: this command will not add any files that are new. It will only commit existing files that have been modified, and will delete any files that you have deleted, from the repository. (Deleted files still exist in the history and can always be recovered.)

$ git commit -am "Updated the widget to widgetize."

Git Configuration

You can have a global Git configuration file, $HOME/\.gitconfig, in which you keep your personal information and command aliases, which is one of three ways you can add your own commands to Git.

[user]
    name = Elf M. Sternberg
    email = someguy@example.com
    
[alias]
    unstage = reset -q HEAD --
    nevermind = !git reset --hard HEAD && git clean -d -f
	wip = for-each-ref --sort='authordate:iso8601' --format='%(color:green)%(authordate:relative)%09%(color:white)%(refname:short)' refs/heads	
    stem = "!f() { git checkout -b $1 develop; }; f"
    start = !git init && git commit --allow-empty -m \"Initial commit\"

Git Aliases

Aliases are commands that you can run in git as if they were part of the git toolset, but their functionality is defined by you. The five aliases shown above are my "must haves." They represent the way I work.

  • unstage is something I do a lot. Maybe it's my ADHD, but I often add something to the git staging area, then realize that the work was incomplete and have to go back. This command does that, and I hated memorizing it.
  • nevermind is for when your work has gone off the rails; your stab at solving the problem has taken you places you didn't want to be. This command resets you to exactly where you were before you started hacking.
  • wip stands for "works in progress"; it shows you a list of branches currently live in your local project, in the order from oldest to newest, with a text that tells you your last commit was "yesterday" or "3 months ago".
  • stem creates a new branch off the develop branch (you can change that to main or canon or whatever). This is the most common workflow I have at home, and this command allows me to get to it quickly. The syntax tells git to use the bash to populate the new branch name, as the default alias format can only take arguments at the end, and the new branch name must be injected before the source branch.
  • start creates a git repository out of a completely empty folder. This might seem odd, but it's actually a very useful way of introducing a new project and ensuring git is ready to go.

Git Extensions

Just like aliases, you can add whole unique commands to git, as long as the extension name doesn't conflict with one of git's internal commands. The syntax for doing so is to create a script (in any language!) and name it git-your-extension-name, and you call it by invoking git and giving it the extension name.

For example, if you write documentation and you want to know how many words you've written since your last commit, you can create a Bash script named git-wc (word count):

#!/bin/bash
REM=`git diff --word-diff=porcelain -U $* | grep '^-' | sed 's/^-//' | wc -w`
ADD=`git diff --word-diff=porcelain -U $* | grep '^+' | sed 's/^+//' | wc -w`
DIF=`expr $ADD - $REM`
echo "Word count: $DIF"

Add vs Commit

You may have noticed that there's a two-step to committing your work; you add it, then commit it. adding it puts it into the staging area. The primary goal of this design is to allow you to commit only parts of your project, rather than committing everything at once. By creating an index of what-to-commit, and then allowing you to write your commit message afterward, you have more control over the development process.

If you're completely reassured of your skillz as a leet koder dood, you could always create an alias that stages, commits, and pushes to your remote repository all at once. I don't recommend that.