Git

Date

November 11, 2020

1 Learning Sources

2 Basic concepts and terms:

  • Overall structure: working tree <-(checkout)-|-(add)-> **staging area** <-(reset)-|-(commit)-> history <-(fetch/pull)-|-(push)-> remote

  • difference: working tree <-> staging area <-> history

  • working tree is also called the workspace

  • staging area is also called as the index, cache, directory cache, current directory cache, staged files (ref). It is a single, large, binary file in <baseOfRepo>/.git/index, which LISTS all files in the current branch, their sha1 checksums, time stamps and the file name – it is NOT another directory with a copy of files in it.

  • history is also called as the local repository. This is a hidden directory (.git) including an objects directory CONTAINING ALL versions of every file in the repo (local branches and copies of remote branches) as a compressed “blob” (Binary Large Object) file. (ref)

  • HEAD is the pointer to the working tree. To find where HEAD points to, run

    cat .git/HEAD
    
  • master is the pointer to the local master branch

  • detached HEAD is the situation where HEAD (current working tree) is not master or with a branch name.

  • WIP means Work In Progress (stashing)

  • origin short name for the location of the remote

  • origin/master is called the remote tracking branch (what the master branch looks like at origin)

  • upstream: let A be a repository, B be a fork of A, C be a local clone of B. Then A is called the upstream of C

  • fetch download remote to the local history

  • push upload the local history to remote

  • merge

  • tag specific points in a repository’s history as being important, eg. v1.0, v2.0, …

  • branch Local branches aren’t automatically synchronized to the remotes so we have to explicitly push the branches you want to share. (TODO: continue to Remote Branch)

3 .gitignore

The file .gitignore lists files, per line, that should be ignored.

  • comments starts with #: # COMMENT

  • we can explicitly specify files, .DS_Store

  • we can use regexp, \*~, \*.log

  • a whole folder is indicated by <FOLDER>/

4 init

git init

5 config

git config --global user.name "<NAME>"
git config -- global user.email "<NAME@EMAIL.ADDRESS>"
git config --local user.name "<NAME>"
git config -- local user.email "<NAME@EMAIL.ADDRESS>"

To list config:

git config --list

6 status

git status

7 log

git log
git log -p
git log -- <FILE>
git log --all --decorate --oneline --graph

It’s convenient to alias this.

8 add: working tree -> staging area

git add FILE

FILE can be a list of files, FILE1 FILE2 FILE3 ... we can use regexp, for eg, S* for all files starting with S

To add all modified files

git add .

10 commit: staging area -> history

git commit

To commit with a short commit message:

git commit -m "<SHORT COMMIT MESSAGE>"

To commit without any commit message:

git commit --no-edit

To amend the last commit:

git commit --amend

(This does changes the ID of the last commit. Amending works only for the latest commit.)

To commit without

11 add+commit: working tree -> staging area and history

git commit -a

nothing to specify after git rm

14 checkout: working tree <- staging area

git checkout -- <FILE>

To place HEAD (i.e., to retrieve) to the state <HASH>:

git checkout <HASH>

<HASH> can be the first five characters

16 checkout branch

git chekout <BRANCH NAME>

17 reset: staging area <- history

git reset HEAD <FILE>

18 branch: list

To list all branches:

git branch

To list merged branches:

git branch --merged

To list local and remote branches:

git branch -a

To list remote tracking branches only:

git branch -r

19 branch: create new

To create a new branch from HEAD:

git branch <BRANCH NAME>

To create + checkout -> new branch:

git branch -b <BRANCH NAME>

20 branch: remove

git branch -d <BRANCH>

21 merge: HEAD -> master

To merge <BRANCH> into master:

git merge <BRANCH>

The response can be different depending on the strategy:

  • fast-forward

  • three-way (recursive)

    • In case of conflict, files with conflict get modified with diff contents. We can check and resolve these conflict by opening those files. When doing this, we also need to delete git markers.

    • After conflicts are resolved, do git status.

    • Aborting the merge process will restore the original file contents:

    git merge --abort
    

If all named commits are already ancestors of HEAD, git merge will exit early with the message “Already up to date.” This is the situation when we try to merge the same branch. In such a situation, differentiate two points by distinct branches, merge, and then remove the unnecessary branch name.

After merging with master branch with another branch, <BRANCH> to say, the branch <BRANCH> that may not be necessary anymore is not automatically deleted. We have to this manually:

git branch -d <BRANCH>

22 restore

$ git checkout <branch> <filename>

will bring back <filename> from <branch>. This can be used when we want to restore a deleted or modified file.

23 Stash: save

To save working directory without staging:

git stash

To stash with comment:

git stash save "<comment>"

24 stash: list

To list all stashes:

git stash list

To list all stashes with changes:

git stash list -p

25 stash: apply

git stash apply
git stash apply <LABEL>

Here, <LABEL> is the one given by stash list

26 clone

git clone git@github.com:name/git.git

27 remote: add/remove

To add a new remote:

git remote add origin <REMOTE REPOSITORY URL>

To add upstream:

git remote add upstream <UPSTREAM REPOSITORY URL>

To remove:

git remote remove <REMOTE NAME>

After modifying remote/upstream, run git remote -v to verify.

28 remote: list

To list remotes (short names only):

git remote

To list remotes (short and full names only):

git remote

To list remotes verbosely:

git remote -v

29 fetch: local repository <- remote repository

git fetch origin

Note that this does not affect local/HEAD. We need to merge, eg. git merge origin/master later.

git fetch upstream

To fetch and merge:

git pull <REMOTE> <BRANCH>

The error “fatal: refusing to merge unrelated histories” may occur when we try to merge/pull unrelated repositories together. For example, we might try to resume old project from scratch while wanting to keep the same GitHub repository. To resolve this:

git pull <REMOTE> <BRANCH> --allow-unrelated-histories

30 push: local repository -> remote repository

git push <REMOTE REPOSITORY: eg. origin> <LOCAL BRANCH: eg. master>
$ git push --set-upstream origin master
To https://...
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://...'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
hbshim@aleph:~/Dropbox/Workspace/math/build/html$ git push -f
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin master
$ git push -f

31 rebase

To “operate on” the last <n> commits back from HEAD:

git rebase -i HEAD~<n>

(-i indicates “interactive”.)

Interactive commands:

  • reword: edit commit message

  • drop: remove commit

We can also reorder commits by changing the order of the lines.

33 tag

To list tags,

git tag

To create an annotated tag named TAG:

git tag -a <TAG> -m "<COMMENT>"

To see the data for the tag named TAG

git show <TAG>

To push the tag TAG to the remote original:

git push origin <TAG>

To push all tags to the remote original:

git push origin --tags

To delete the tag TAG:

git tag -d <TAG>

Caution: This does not remove TAG from the remote.

To delete the tag TAG from the remote original:

git push origin --delete <TAG>

To checkout TAG:

git checkout <TAG>

This will cause the “detached HEAD” state since what was checked out is merely a commit hash not a branch (even if there was branch tip pointing to the commit TAG). We need to branch out to work on and modify the commit hash TAG:

git checkout -b <BRANCH> <TAG>

git should respond with the message “Switched to a new branch <BRANCH>.”