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