git quick reference

Getting Started

git init

Creates a .git subdirectory to keep all of the necessary metadata for the repo. Each developer's local repository is a buffer between their contributions and the remote/shared project repository.
 

Project/Repository State Transition

commit is not push ;)
 
Working directory ==> edit ==> git add ==> Local Staging area ==> git commit => Local Repository ==> git push ==> Remote/Shared Repository
 
 

git add <file>|<directory>

Adds a change in <file> or <directory> to the staging area, but the changes are not actually recorded until git commit. The staging area is a buffer between the working directory and the project repository/history.
 
 
 

git commit

Commits the staged snapshot to the local repository (project history). The entire commit should be summarized on the first line in less than 50 characters, followed by a blank line, then a detailed explanation of what's been changed.
 
 

git status
 

Displays the state of the working directory and the staging area:
 
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    # Changes not staged for commit:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    # Untracked files:
    #   (use "git add <file>..." to include in what will be committed)
 
 
 

git log

Displays committed snapshots. The 40-character SHA-1 checksum string also serves as unique hash ID.
 
 
 

git checkout <commit>

Update all files in the working directory to match the commit specified by hash ID or tag. After the checkout, HEAD points directly to the <commit>, and this could end up in a "detached HEAD" state if the HEAD no longer points to master or some other local branch.
 

 
 

Revert, Reset & Clean

 

git revert <commit>
 

"Safely" undoes a single <commit> at an arbitrary point in the history by generates a new commit that undoes all of the changes introduced in <commit>, then apply it to the current branch. Complete history of the repository is preserved.
 

git reset
 

"Permanently" removes changes by working backwards from the current commit and wiping it from the project repository history. So it should only be used to undo local changes from staging area.

git reset --hard
 

Resets the Staging Area and the Working Directory to match the most recent commit. In addition to unstaging changes, the --hard flag tells Git to overwrite all changes in the working directory. Use git clean to remove untracked (that is not yet "git add"ed) files from working directory.
 
    # Create a new file called `foo.py` and add some code to it
    # Commit it to the project history
    git add foo.py
    git commit -m "Start developing a crazy feature"
    # Edit foo.py again and change some other tracked files, too
    # Commit another snapshot
    git commit -a -m "Continue my crazy feature"
    # Decide to scrap the feature and remove the associated commits
    git reset --hard HEAD~2
    # Moves the current branch backward by two commits, effectively removing the two "crazy feature" snapshots from the project history.
 

revert or reset ?
 

Whereas git revert is designed to safely undo a public commit, git reset is designed to undo local changes. Because of their distinct goals, the two commands are implemented differently: resetting completely removes a changeset, whereas reverting maintains the original changeset and uses a new commit to apply the undo.
 

git clean

Removes untracked files from working directory.
 
 

 

 

Branches

 

Checkout Branch

git checkout -b <new-branch> <existing-branch> is equivalent to this sequence:
    git branch <new-branch> <existing-branch>
    git checkout <new-branch>
 

Commit New Branch

    Make necessary modifications by editing required files, and:
    git add <file>
    git commit -m "Started work on a new branch"
    # Repeat

Merge Branches
 

Takes the independent lines of development created by git branch and integrate them into a single branch. Based on the structure of branches, git internally chooses a suitable merging algo:
  • A fast-forward merge can occur when there is a linear path from the current branch tip to the target branch. Since there is really nothing to merge, git simply moves the current branch tip up to the target branch tip.
  • A fast-forward merge is not possible if the branches have diverged. Git has to combine the forks via a 3-way merge (two branch tips and their common ancestor).
Developers typically use rebasing followed by (fast-forward) merge for small features or bug fixes, while reserving 3-way merges for the integration of longer-running features by joining of two branches.
 
 

Rebase

Rebasing is like saying, "(Instead of a fork,) I want to base my changes on what everybody has already done."
 
    ## Rebase and Merge to maintain a linear project history::
    # Start a new feature
    git checkout -b new-feature master
    # Edit files
    git commit -a -m "Start developing a feature"
 
    ## In the middle of our feature, we realize there's a security hole in our project
    # Create a hotfix branch based off of master
    git checkout -b hotfix master
    # Edit files
    git commit -a -m "Fix security hole"
 
    # Merge hotfix back into master
    git checkout master
    git merge hotfix
    git branch -d hotfix
 
    ## Integrate the feature branch with a rebase to maintain a linear history:
    git checkout new-feature
    git rebase master
    # Now "master" is still in its old place and not yet referring to new-feature, which is a new tip after rebasing.
 
    ## Fast-forward merge sets "master" to new-feature, which is a new tip after rebasing)
    git checkout master
    git merge new-feature
 
 
 
 
 

Remote/Shared repositories

git init --bare <my-project>

Bare version of a repository is stored in directory called <my-project>.git.
 

git clone <repourl>

Copies the repository located at <repourl> onto working directory on local machine, and creates a remote connection called "origin" pointing back to the original repository.
 

git remote add john http://dev.example.com/john.git

Creates connection shortcut "john" to access his (public) repository. HTTP provides anonymous read-only access; need SSH for read-write access.
 

git fetch <remote>

Imports branches & commits from the <remote> repository into local repo. The resulting commits are stored as remote branches instead of the normal local branches. Useful to safely review commits made by other people before integrating them with your local repository.
 

git pull <remote>

Fetches the <remote> copy of the current branch and immediately merges it into the local copy.
        ## git pull is equivalent to:
        git fetch <remote>
        git merge origin/<current-branch>
 
 

git pull --rebase <remote>

Instead of using git merge to integrate the remote branch with the local one, uses git rebase. This creates linear history by putting local changes on top of what everybody else has already contributed and prevents unnecessary merge commits.
        git checkout master
        git pull --rebase origin
 

git push <remote> <branch>

Transfers commits from local repository <branch> to the <remote> repo.
    ## Local linear integration of local repository with the shared/remote repository and publishing the contributions:
    git checkout master
    git fetch origin master
    git rebase -i origin/master
    # Squash commits, fix up commit messages etc.
    git push origin master
 
 
 
 

Tree view of repository


Tree view of commits/branches/merges

git log --graph --all --date-order
# crisp/short version:
git log --graph --all --oneline --date-order
 
 

Show local and remote branch commits

git show-branch --all
    * branch head
    ! other heads
    If a commit is on the I-th branch, the I-th indentation character shows a + sign; otherwise it shows a space.
 
 

Compare two commits

git diff --name-only bb46a8d a6bf256
 
 
 
 
 

Amending Past Commits

 

Amending the message of the most recently pushed commit


git commit --amend
    Change message. Save & Quit.
done!
# git push --force    # for remote
 
 

Amending a previous incomplete commit


    # Edit hello.py and main.py
    git add hello.py
    git commit
    # Realize you forgot to add the changes from main.py
    git add main.py
    git commit --amend --no-edit
    # The editor will be populated with the message from the previous commit. Resulting commit
    # will look like we committed the changes to hello.py and main.py in a single snapshot.
    # git push --force    # for remote
 
 

Amending the message of older or multiple commit messages

git rebase -i HEAD~3 # Displays a list of the last 3 commits on the current branch 
  • Replace "pick" with "reword" before each commit message you want to change. Don't change the message yet. Save & Quit.
  • Change the message for shown commit. Save & Quit. -- gets repeated once per command/"reword".
 
done!
# git push --force    # for remote
 
 
 


No comments:

Post a Comment