Computer

Git Distributed Revision Control System

search

Git Distributed Revision Control System

  • Precautions
  • Non-Medical
  1. Not for Medical Care
    1. The author uses several software packages and programming languages to develop FPnotebook content
    2. For convenience, a dozen pages in FPNotebook are dedicated to quick notes on content creation
  2. These git related notes are intended for the author of this website to have a quick reference for his own use
  3. Use these git related notes with caution (there are pitfalls, and there are likely better commands)
  • Background
  • Windows Set-up
  1. Run git via powershell instead of Git-Bash
    1. Use Posh-Git package
    2. Use Powershell without the ISE (which otherwise tends to hang)
  2. Open via windows explorer
    1. Type powershell in the Address Bar (older windows versions)
    2. Use open powershell here menu option
      1. Shift-Right Click in file window for advanced context menu to see Powershell option
  • Background
  • Git Infrastructure
  1. Source control system created by Linus Torvalds (Linux creator)
  2. Organized as a file management system with an embedded history of each file object and efficient storage
    1. Within a refs folder, branch and tag files point to specific commits
    2. A HEAD file points to the current branch or to a commit (if detached)
  3. Every commit is represented by a file containing meta data (e.g creator, date-time) and pointer keys to blobs and trees
    1. Each pointer key is a SHA1 hash of content within a file and is unique and immutable
    2. Each SHA1 Hash is stored only once, so storage and processing is efficient
    3. Blobs are actual data, while trees point to sub-levels of objects that also contain blobs and trees
  • Approach
  • Local Git Repository
  1. Commits
    1. Each commit represents a snapshot history of files at a single point of time
    2. Commits are keyed with a SHA1 Hash that includes time and date, creator and a message
    3. Commits are pointed to by various objects
      1. Branches (e.g. master)
      2. Tags
      3. HEAD (current branch or detached to point to any commit)
    4. To create a commit
      1. Stage content with "git add -A" to add all content or add individual filenames
      2. Commit (with a message) the staged content with 'git commit -m "first commit" '
      3. To combine staging and commit: "git commit -a -m "first commit"
      4. "Git Push Origin Master" moves the content to remote server
    5. Selecting Commits: Checkout
      1. "git checkout commitX" moves the HEAD to a specific commit, independent of branches
      2. Refer to commits by the start of their hash, that identifies the commit uniquely (as few as first 4 letters)
      3. May also use a relative reference (master^^ or master~3) as described below (under HEAD section)
    6. Log
      1. "git log" shows a list of commits, each with their associated SHA1, message, and other meta data
      2. "git log --oneline" (aka "git log --pretty=oneline --abbrev-commit")
        1. Displays an abbreviated SHA and first line of message
    7. Moving Commits: Cherry-Pick
      1. Selects a list of commits, and appends a copy of these commits to the current commit (HEAD)
      2. "git cherry pick c3 c7" appends a copy of c3 and c7 onto the current commit (leaving c3, c7 in original position)
    8. Moving Commits: Interactive Rebase
      1. Similar to Cherry-Pick, but provides an interactive window to select and reorder commits
      2. "git rebase -i HEAD~3"
        1. Starts at 3 commits back from HEAD
        2. Interactively select which commits to append and in what order
        3. Git will append copies of these selected commits to the position HEAD~3
        4. The branch and HEAD pointer will now point to the last commit of those appended
        5. The old commits in therir original order still exist until garbage collection
          1. The prior commit chain may be maintained with "git branch newBranch oldCommit"
          2. Where oldCommit is the last commit in the old chain that you wish to maintain
  2. Branches
    1. Branches are pointers to commits (including all of the changes from the parent commits)
    2. "Master" is a default main branch created when a git repository is initialized
    3. Checkout
      1. "git checkout myBranch" changes the HEAD to point to "myBranch"
      2. "git checkout -b newBranch" creates a new branch and checks out that new branch
    4. Switch
      1. "git switch myBranch" changes the HEAD to point to "myBranch" (identical to Checkout)
      2. Switch was added to Git more recently, as a simple command that only switches branches
    5. Create a new branch without checking it out
      1. "git branch newBranch" creates a new branch at the current commit (HEAD)
      2. "git branch newBranch c4" creates a new branch pointing to the commit c4
    6. Move a branch pointer to a different commit (uses force, -f flag)
      1. "git branch -f myBranch e634" moves myBranch to point to e634 commit
      2. "git branch -f myBranch HEAD^^" moves myBranch to point 2 commits back from the HEAD
    7. Merging
      1. Assume our current branch is newBranch ("git checkout newBranch")
      2. "git merge master" will merge the currently active newBranch with the master branch
      3. The merge creates a new commit with 2 parents (newBranch and master)
        1. master will now be the active branch and will point to the new merged commit
        2. newBranch will still point to the commit before the merge
      4. newBranch can be fast-forwarded to the current master merged position (repeating the last command)
        1. "git checkout newBranch; git merge master" fast-forwards the newBranch
        2. Now newBranch and master both point to the same merged commit
    8. Rebase
      1. Rebase creates a linear chain of commits each with a single parent
        1. Contrast with merge, which creates a new commit with 2 parents
        2. This leads to a cleaner, straight line history contrasted with the more branched structure with merges
        3. However rebase modifies the commit tree history from its original branched structure
          1. Rebase copies (and appends selected commits), with prior commit structure garbage collected
      2. "git rebase master" copies the commits unique to currentBranch, and appends them onto master
        1. currentBranch points to the latest combination of the 2 chains
        2. master still points to the commit before currentBranch commits were appended
      3. master can be fast-forwarded to the currentBranch rebased position (repeating the last command)
        1. "git checkout master; git rebase currentBranch" fast-forwards master
        2. Now master and currentBranch both point to the same combined head
  3. Tags
    1. Tags are similar to branches in that they point to a specific commit
      1. However, unlike branches, Tags are static, and do not move forward as commits are added
      2. This allows Tag assignment to stay anchored to a specific commit and function as a milestone, or version pointer
    2. Assign a New Tag
      1. "git tag v2 c15" assigns the Tag V2 to the commit c15
    3. Describe
      1. Reports the current position in relation to the closest tag
      2. Example Command: "git describe refName"
        1. Where refName is a commit SHA1, branch name, HEAD relative reference (^~) or similar
      3. Example Response: "v2_4_c5"
        1. Where v2 is the most recent tag in the refNames chain
        2. Where 4 is the number of commits ahead of the v2 tag
        3. Where c5 is the commit pointed to by refName
  4. HEAD
    1. HEAD normally points to the current branch name, which in turn points to a commit
    2. HEAD can also be detached from a branch, and point directly at a commit
      1. "git checkout commitHash" where commitHash is the first 4-6 chars in the commit's hash key
    3. Moving HEAD to relative references: The Caret (^)
      1. "git checkout master^" will checkout the first parent of master branch (^^ for grandparent, ^^^ for great...)
      2. "git checkout HEAD^^" will checkout the grandparent of the current HEAD position's commit
      3. "git checkout HEAD^2" will follow a second parent branch preceding the current commit
        1. A commit consisting of a merge will have 2 parents (that came together for the current commit)
        2. "git checkout HEAD^" will checkout the first parent
        3. "git checkout HEAD^2" will checkout the second parent
    4. Moving HEAD to relative references: The Tilde (~)
      1. "git checkout HEAD~4" will checkout the commit that is at 4 consecutive parents preceding the HEAD
    5. Moving HEAD to relative references: Chaining relative references
      1. "git checkout HEAD~^2~3"
        1. Go back one commit (~)
        2. Then go back one commit, to the second parent of the merged commit (^2)
        3. Then go back 3 commits (~3)
    6. We can also force the current branch pointer a certain number of commits up from the HEAD
      1. "git branch -f master HEAD~2" will move master branch to point to the commit 2 above the HEAD
      2. Caution: Avoid orphaning the 2 commits after the new master branch repositioning
        1. If the HEAD is also moved, these commits will only be accessible by their hashes
        2. Garbage collection will occur if there is no branch pointer, tag or HEAD to a chain of commits
  5. Undoing
    1. Reset
      1. Move back in time to prior commit, as if subsequent commits never occurred
      2. "git reset HEAD~2" will move the current branch back 2 commits (similar to "git branch -f master HEAD~2")
      3. However, with reset, remote branches (origin) are not affected, unlike with revert command (see below)
    2. Revert
      1. Creates a new commit that undoes the prior commits
      2. "git revert HEAD" adds a commit that reverses the most recent commit locally
      3. "git revert HEAD^" adds a commit that reverses the last 2 most recent commits locally
      4. Pushing (git push) these commits to the remote server will persist the reversal remotely
  • Approach
  • Remote Git Repository
  1. Background
    1. Remote repositories serve as both a server based backup and a central shared data source
    2. Regardless of the web wrapper (e.g. github, gitlab, bitbucket), underlying remote git functionality remains the same
  2. Create a copy of a remote repository
    1. "git clone PATH" creates a local copy of the remote repository
    2. In many cases, the clone is used only to download the files, but not to push data back to the server
  3. Remote Branch Basics
    1. Default branch is origin/master (e.g. when cloning a repository)
    2. Remote branches default to detached HEAD mode when checked out locally
    3. Remote branch tracking
      1. Remote branch tracking is established on cloning a repository
      2. Local branch (e.g. master) is automatically set to track a remote branch (e.g. origin master)
      3. Remote branch to track may be explicitly defined when creating a local branch
        1. "git checkout -b newBranch origin master"
        2. In this case, local "newBranch" will track the remote "origin master"
      4. Remote branch to track may also be explicitly defined for a pre-existing branch
        1. "git branch -u origin master aBranch" (aBranch may be left off if it is the current branch)
        2. In this case, local "aBranch" will track the remote "origin master"
    4. "git checkout"
      1. Checkout a remote branch with "git checkout origin master"
      2. When we commit to this branch, HEAD will point to the commit
        1. However, both origin/master and master point to the commit before the current commit
    5. "git fetch"
      1. Downloads remote commits on the current branch, but does not modify the local state
      2. The remote branch (e.g. origin master) pointer is updated on local repo to point to most recent commit
      3. However, the local branch (e.g master) still points to the commit before the fetch
      4. To incorporate the remote commits into the current branch after a fetch, an additional command is needed
        1. "git merge origin master" OR
        2. "git rebase origin master" OR
        3. "git cherry-pick origin master"
    6. "git pull"
      1. Combines a fetch AND merge in one command, incorporating the remote commits with the local commits
    7. "git push"
      1. Publishes local work to the remote repository
      2. For example, a new commit c1 is added to the local master branch
        1. "git push" will copy the commit c1 to the server and update origin master to point to c1
  4. Conflicts: Local work has diverged from the Remote git repository
    1. Local commits cannot be pushed to remote (contains other commits not yet pulled to local)
    2. Fix: Git Rebase
      1. "git fetch" (downloads the current branch commits from remote)
      2. "git rebase origin master" (copies current commit chain pointed to by HEAD, onto the origin master position)
      3. 'git push'
    3. Fix: Git Rebase with Pull
      1. "git pull --rebase" (combines fetch and rebase commands from the first Git Rebase approach)
      2. "git push"
    4. Fix: Git Merge
      1. "git fetch"
      2. "git merge origin master" (creates a new commit with 2 parents, one from remote, and the other local)
      3. "git push"
    5. Fix: Git Merge with Pull
      1. "git pull" (combines fetch and merge commands from the first Git Merge approach)
      2. "git push"
    6. Fix: Git Push Force
      1. This is destructive as it replaces the remote branch with whatever is local (Exercise caution)
      2. Any commits by other users that are not in the local branch will be lost!
      3. Consider other options (e.g. revert)
      4. Not Ideal Technique (messy, risky) compared with revert which is straight forward
        1. "git push --force origin master" (or replace master with branch-name)
        2. If commit checked out, and head is detached, first "git branch -f master HEAD"
        3. On other local computers
          1. "git fetch --all; git branch backup-master; git reset --hard origin/master"
          2. https://stackoverflow.com/a/8888015
  • Technique
  • Git Commands
  1. Adding (Staging)
    1. git add PATH
      1. Stage specified in the file path (e.g. PATH of '*.txt' adds all files in dir with txt extension, quotes required)
      2. PATH may contain folders or subfolders (e.g. folder1, mainFolder/subfile.txt)
      3. PATH may be multiple files that are space delimited ("git add file1.js file2.js file3.js")
    2. git add -A
      1. Stages all files (new, modified, deleted)
      2. May require :/ at end of line to add the entire directory tree in the git repository
    3. git add .
      1. Stages all new and modified files but NOT deleted (in newer versions of git, all files are actually staged)
      2. Refers to staging all files in current directory and in all subdirectories
    4. git add -u
      1. Stages all modified and deleted files but NOT new
  2. Removing (from staged)
    1. git reset PATH
      1. Removes file or files specified in PATH from the staged files
      2. This however leaves the files but unstages them from the repository
    2. git rm PATH
      1. Physically removes file or files in the PATH (deletes the files)
      2. Removes the files from the git repository
  3. Committing to local repository
    1. git commit -m "description"
  4. Reverting a commit
    1. git revert KEY-ID
      1. Where KEY-ID is the ID of the commit to revert
      2. Adds anything that was removed in that commit and removes anything added
      3. Maintains history (safest undo strategy)
  5. Reverting to previously saved version of a file
    1. git checkout -- PATH
      1. Reverts file or files in PATH to prior status from the last commit
  6. Branching
    1. git branch BRANCH
      1. Where BRANCH is the new branch name to create
    2. git checkout BRANCH
      1. Switch to BRANCH from the current branch (e.g. master)
    3. git checkout master
      1. Return to the main branch, in this case, master
      2. Perform this prior to merging a branch into master
    4. git merge BRANCH
      1. Merges changes in BRANCH into the currently active branch (e.g. master or other main branch)
    5. git branch -d BRANCH
      1. Delete branch named BRANCH from the current repository
  7. Adding a remote repository
    1. git remote add origin URL
      1. Where URL is the location of the remote repository (e.g. https://github.com/you/your_git.git)
  8. Storing changed files (not added/committed) in stash and setting head to last committed changes
    1. git stash
      1. Useful if local commit has a few insignificant file changes and need to pull from origin master
  9. Synchronizing with remote repository
    1. git push ALIAS BRANCH
    2. git push origin BRANCH
      1. If BRANCH is left blank, pushes the remote changes to the origin branch of the same name
      2. If BRANCH is set to MASTER, then changes are written to the origin master
    3. git push -u origin BRANCH
      1. Current parameters (e.g. BRANCH = master) are saved if -u is specified
      2. Future calls to "git push" without parameters will assume, in this case, defaulted "origin master"
    4. git pull
      1. Downloads and incorporates changes from remote repository
    5. git merge BOOKMARK / BRANCH
      1. Merges the bookmarked branch into the current local working branch
    6. git fetch BOOKMARK
      1. Downloads all bookmark history from the remote repository
  • Technique
  • Utility Functions
  1. git status
    1. Show current git repository status
  2. git log
    1. Show repository history of commits
  3. git diff HEAD
    1. Shows differences between current status and most recent commit
  4. git diff --staged
    1. Shows file differences between what is staged and what was last committed
  5. git remote show origin
    1. Origin URL, configuration for push/pull and current branch
  6. git config credential.helper store
    1. Enables git to save credentials for the current repository when entered the next time
    2. Precaution: Storage of git credentials is stored in a plain text file (not encrypted)
  • Technique
  • Rescue methods for give-up situations
  1. Reset remote-master to origin, while still maintaining local files
    1. Perform "git add" and "git commit" first on local repository
    2. git fetch origin master
    3. git merge -s recursive -X theirs origin/master
  2. Reset remote-master to origin-master (local repository is completely overwritten)
    1. git reset origin/master
      1. Resets the remote master to origin master, but retain files in the local directory
    2. git reset --hard origin/master
      1. Resets the remote master to origin master AND overwrites or deletes files in the local directory
  3. Reset the git cache to abide by git.ignore (Visual Studio sometimes includes files despite their being in ignore)
    1. First add and commit any pending changes
    2. git rm -r --cached .
    3. git add .
    4. git commit -m "re-setting git cache based on updated .gitignore"