2022-04-29 18:03:21 +00:00
|
|
|
+++
|
|
|
|
title = "Git Notes"
|
|
|
|
description = "Basic documentation of Git"
|
|
|
|
date = 2022-04-27T18:00:00+00:00
|
|
|
|
updated = 2022-04-27T18:00:00+00:00
|
2022-06-09 03:50:30 +00:00
|
|
|
template = "section.html"
|
2022-04-29 18:03:21 +00:00
|
|
|
sort_by = "weight"
|
|
|
|
weight = 6
|
|
|
|
draft = false
|
|
|
|
[taxonomies]
|
|
|
|
documentation=["Reference"]
|
|
|
|
categories=["Git", "Version Control", "VCS"]
|
|
|
|
+++
|
|
|
|
|
|
|
|
[Git](https://git-scm.com/) 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:
|
|
|
|
|
2022-06-14 01:25:11 +00:00
|
|
|
```bash
|
2022-04-29 18:03:21 +00:00
|
|
|
$ mkdir a-new-project
|
2022-06-14 01:25:11 +00:00
|
|
|
$ touch README.md
|
2022-04-29 18:03:21 +00:00
|
|
|
$ git init
|
|
|
|
```
|
|
|
|
|
|
|
|
This creates a new folder, `.git`, where Git will store your commit history and
|
2022-06-14 01:25:11 +00:00
|
|
|
some configuration details. Git will usually not create a repository without
|
|
|
|
_something_ to store in it, but see the [`git start` alias](#config) below.
|
2022-04-29 18:03:21 +00:00
|
|
|
|
|
|
|
## 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:
|
|
|
|
|
2022-06-14 01:25:11 +00:00
|
|
|
```bash
|
2022-04-29 18:03:21 +00:00
|
|
|
$ 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:
|
|
|
|
|
2022-06-14 01:25:11 +00:00
|
|
|
```bash
|
2022-04-29 18:03:21 +00:00
|
|
|
$ 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.)
|
|
|
|
|
2022-06-14 01:25:11 +00:00
|
|
|
```bash
|
2022-04-29 18:03:21 +00:00
|
|
|
$ git commit -am "Updated the widget to widgetize."
|
|
|
|
```
|
|
|
|
|
2022-06-14 01:25:11 +00:00
|
|
|
## Git Configuration {#config}
|
2022-04-29 18:03:21 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
2022-06-14 01:25:11 +00:00
|
|
|
```bash
|
2022-04-29 18:03:21 +00:00
|
|
|
[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
|
2022-06-14 01:25:11 +00:00
|
|
|
stem = "!f() { git checkout -b $1 develop; }; f"
|
2022-04-29 18:03:21 +00:00
|
|
|
start = !git init && git commit --allow-empty -m \"Initial commit\"
|
|
|
|
```
|
|
|
|
|
2022-06-14 01:25:11 +00:00
|
|
|
## Git Aliases {#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):
|
|
|
|
|
|
|
|
``` bash
|
|
|
|
#!/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. `add`ing 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.
|
|
|
|
|
2022-04-29 18:03:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|