Git Commands Notes
Git Commands Notes
Git Commands
WWW.LEARNLONER.COM
Contents
About ................................................................................................................................................................................... 1
Chapter 1: Getting started with Git ...................................................................................................................... 2
Section 1.1: Create your first repository, then add and commit files ........................................................................ 2
Section 1.2: Clone a repository ..................................................................................................................................... 4
Section 1.3: Sharing code .............................................................................................................................................. 4
Section 1.4: Setting your user name and email .......................................................................................................... 5
Section 1.5: Setting up the upstream remote .............................................................................................................. 6
Section 1.6: Learning about a command .................................................................................................................... 6
Section 1.7: Set up SSH for Git ...................................................................................................................................... 6
Section 1.8: Git Installation ............................................................................................................................................ 7
Chapter 2: Browsing the history ......................................................................................................................... 10
Section 2.1: "Regular" Git Log ..................................................................................................................................... 10
Section 2.2: Prettier log ............................................................................................................................................... 11
Section 2.3: Colorize Logs ........................................................................................................................................... 11
Section 2.4: Oneline log .............................................................................................................................................. 11
Section 2.5: Log search ............................................................................................................................................... 12
Section 2.6: List all contributions grouped by author name ................................................................................... 12
Section 2.7: Searching commit string in git log ........................................................................................................ 13
Section 2.8: Log for a range of lines within a file ..................................................................................................... 14
Section 2.9: Filter logs ................................................................................................................................................. 14
Section 2.10: Log with changes inline ........................................................................................................................ 14
Section 2.11: Log showing commited files ................................................................................................................. 15
Section 2.12: Show the contents of a single commit ................................................................................................ 15
Section 2.13: Git Log Between Two Branches ........................................................................................................... 16
Section 2.14: One line showing commiter name and time since commit .............................................................. 16
Chapter 3: Working with Remotes ..................................................................................................................... 17
Section 3.1: Deleting a Remote Branch ..................................................................................................................... 17
Section 3.2: Changing Git Remote URL ..................................................................................................................... 17
Section 3.3: List Existing Remotes .............................................................................................................................. 17
Section 3.4: Removing Local Copies of Deleted Remote Branches ....................................................................... 17
Section 3.5: Updating from Upstream Repository .................................................................................................. 18
Section 3.6: ls-remote ................................................................................................................................................. 18
Section 3.7: Adding a New Remote Repository ....................................................................................................... 18
Section 3.8: Set Upstream on a New Branch ........................................................................................................... 18
Section 3.9: Getting Started ........................................................................................................................................ 19
Section 3.10: Renaming a Remote ............................................................................................................................. 19
Section 3.11: Show information about a Specific Remote ........................................................................................ 20
Section 3.12: Set the URL for a Specific Remote ...................................................................................................... 20
Section 3.13: Get the URL for a Specific Remote ...................................................................................................... 20
Section 3.14: Changing a Remote Repository .......................................................................................................... 20
Chapter 4: Staging .................................................................................................................................................... 21
Section 4.1: Staging All Changes to Files ................................................................................................................... 21
Section 4.2: Unstage a file that contains changes ................................................................................................... 21
Section 4.3: Add changes by hunk ............................................................................................................................ 21
Section 4.4: Interactive add ........................................................................................................................................ 22
Section 4.5: Show Staged Changes ........................................................................................................................... 22
Section 4.6: Staging A Single File ............................................................................................................................... 23
LearnLoner.com
Section 4.7: Stage deleted files .................................................................................................................................. 23
Chapter 5: Ignoring Files and Folders .............................................................................................................. 24
Section 5.1: Ignoring files and directories with a .gitignore file ............................................................................... 24
Section 5.2: Checking if a file is ignored ................................................................................................................... 26
Section 5.3: Exceptions in a .gitignore file ................................................................................................................. 27
Section 5.4: A global .gitignore file ............................................................................................................................ 27
Section 5.5: Ignore files that have already been committed to a Git repository ................................................. 27
Section 5.6: Ignore files locally without committing ignore rules ........................................................................... 28
Section 5.7: Ignoring subsequent changes to a file (without removing it) ............................................................ 29
Section 5.8: Ignoring a file in any directory .............................................................................................................. 29
Section 5.9: Prefilled .gitignore Templates ............................................................................................................... 29
Section 5.10: Ignoring files in subfolders (Multiple gitignore files) ......................................................................... 30
Section 5.11: Create an Empty Folder ........................................................................................................................ 31
Section 5.12: Finding files ignored by .gitignore ....................................................................................................... 31
Section 5.13: Ignoring only part of a file [stub] ........................................................................................................ 32
Section 5.14: Ignoring changes in tracked files. [stub] ............................................................................................ 33
Section 5.15: Clear already committed files, but included in .gitignore ................................................................. 34
Chapter 6: Git Di ....................................................................................................................................................... 35
Section 6.1: Show dierences in working branch ..................................................................................................... 35
Section 6.2: Show changes between two commits .................................................................................................. 35
Section 6.3: Show dierences for staged files .......................................................................................................... 35
Section 6.4: Comparing branches ............................................................................................................................. 36
Section 6.5: Show both staged and unstaged changes .......................................................................................... 36
Section 6.6: Show dierences for a specific file or directory .................................................................................. 36
Section 6.7: Viewing a word-di for long lines ......................................................................................................... 37
Section 6.8: Show dierences between current version and last version ............................................................. 37
Section 6.9: Produce a patch-compatible di .......................................................................................................... 37
Section 6.10: dierence between two commit or branch ........................................................................................ 38
Section 6.11: Using meld to see all modifications in the working directory ........................................................... 38
Section 6.12: Di UTF-16 encoded text and binary plist files .................................................................................. 38
Chapter 7: Undoing .................................................................................................................................................... 40
Section 7.1: Return to a previous commit ................................................................................................................. 40
Section 7.2: Undoing changes .................................................................................................................................... 40
Section 7.3: Using reflog ............................................................................................................................................. 41
Section 7.4: Undoing merges ..................................................................................................................................... 41
Section 7.5: Revert some existing commits .............................................................................................................. 43
Section 7.6: Undo / Redo a series of commits ......................................................................................................... 43
Chapter 8: Merging .................................................................................................................................................... 45
Section 8.1: Automatic Merging .................................................................................................................................. 45
Section 8.2: Finding all branches with no merged changes ................................................................................... 45
Section 8.3: Aborting a merge ................................................................................................................................... 45
Section 8.4: Merge with a commit ............................................................................................................................. 45
Section 8.5: Keep changes from only one side of a merge .................................................................................... 45
Section 8.6: Merge one branch into another ............................................................................................................ 46
Chapter 9: Submodules ........................................................................................................................................... 47
Section 9.1: Cloning a Git repository having submodules ....................................................................................... 47
Section 9.2: Updating a Submodule .......................................................................................................................... 47
Section 9.3: Adding a submodule .............................................................................................................................. 47
Section 9.4: Setting a submodule to follow a branch .............................................................................................. 48
Section 9.5: Moving a submodule .............................................................................................................................. 48
LearnLoner.com
Section 9.6: Removing a submodule ......................................................................................................................... 49
Chapter 10: Committing ........................................................................................................................................... 50
Section 10.1: Stage and commit changes .................................................................................................................. 50
Section 10.2: Good commit messages ...................................................................................................................... 51
Section 10.3: Amending a commit ............................................................................................................................. 52
Section 10.4: Committing without opening an editor ............................................................................................... 53
Section 10.5: Committing changes directly ............................................................................................................... 53
Section 10.6: Selecting which lines should be staged for committing .................................................................... 53
Section 10.7: Creating an empty commit .................................................................................................................. 54
Section 10.8: Committing on behalf of someone else ............................................................................................. 54
Section 10.9: GPG signing commits ............................................................................................................................ 55
Section 10.10: Commiting changes in specific files ................................................................................................... 55
Section 10.11: Committing at a specific date ............................................................................................................. 55
Section 10.12: Amending the time of a commit ........................................................................................................ 56
Section 10.13: Amending the author of a commit ..................................................................................................... 56
Chapter 11: Aliases ...................................................................................................................................................... 57
Section 11.1: Simple aliases .......................................................................................................................................... 57
Section 11.2: List / search existing aliases ................................................................................................................. 57
Section 11.3: Advanced Aliases ................................................................................................................................... 57
Section 11.4: Temporarily ignore tracked files .......................................................................................................... 58
Section 11.5: Show pretty log with branch graph ..................................................................................................... 58
Section 11.6: See which files are being ignored by your .gitignore configuration ................................................. 59
Section 11.7: Updating code while keeping a linear history ..................................................................................... 60
Section 11.8: Unstage staged files .............................................................................................................................. 60
Chapter 12: Rebasing ................................................................................................................................................ 61
Section 12.1: Local Branch Rebasing ......................................................................................................................... 61
Section 12.2: Rebase: ours and theirs, local and remote ......................................................................................... 61
Section 12.3: Interactive Rebase ................................................................................................................................ 63
Section 12.4: Rebase down to the initial commit ...................................................................................................... 64
Section 12.5: Configuring autostash .......................................................................................................................... 64
Section 12.6: Testing all commits during rebase ...................................................................................................... 65
Section 12.7: Rebasing before a code review ........................................................................................................... 65
Section 12.8: Aborting an Interactive Rebase ........................................................................................................... 67
Section 12.9: Setup git-pull for automatically perform a rebase instead of a merge ......................................... 68
Section 12.10: Pushing after a rebase ........................................................................................................................ 68
Chapter 13: Configuration ...................................................................................................................................... 69
Section 13.1: Setting which editor to use .................................................................................................................... 69
Section 13.2: Auto correct typos ................................................................................................................................. 69
Section 13.3: List and edit the current configuration ................................................................................................ 70
Section 13.4: Username and email address .............................................................................................................. 70
Section 13.5: Multiple usernames and email address .............................................................................................. 70
Section 13.6: Multiple git configurations .................................................................................................................... 71
Section 13.7: Configuring line endings ....................................................................................................................... 72
Section 13.8: configuration for one command only ................................................................................................. 72
Section 13.9: Setup a proxy ......................................................................................................................................... 72
Chapter 14: Branching .............................................................................................................................................. 74
Section 14.1: Creating and checking out new branches ........................................................................................... 74
Section 14.2: Listing branches .................................................................................................................................... 75
Section 14.3: Delete a remote branch ........................................................................................................................ 75
Section 14.4: Quick switch to the previous branch ................................................................................................... 76
LearnLoner.com
Section 14.5: Check out a new branch tracking a remote branch ......................................................................... 76
Section 14.6: Delete a branch locally ......................................................................................................................... 76
Section 14.7: Create an orphan branch (i.e. branch with no parent commit) ....................................................... 77
Section 14.8: Rename a branch ................................................................................................................................. 77
Section 14.9: Searching in branches .......................................................................................................................... 77
Section 14.10: Push branch to remote ........................................................................................................................ 77
Section 14.11: Move current branch HEAD to an arbitrary commit ......................................................................... 78
Chapter 15: Rev-List .................................................................................................................................................. 79
Section 15.1: List Commits in master but not in origin/master ............................................................................... 79
Chapter 16: Squashing .............................................................................................................................................. 80
Section 16.1: Squash Recent Commits Without Rebasing ........................................................................................ 80
Section 16.2: Squashing Commit During Merge ....................................................................................................... 80
Section 16.3: Squashing Commits During a Rebase ................................................................................................. 80
Section 16.4: Autosquashing and fixups .................................................................................................................... 81
Section 16.5: Autosquash: Committing code you want to squash during a rebase ............................................. 82
Chapter 17: Cherry Picking ..................................................................................................................................... 83
Section 17.1: Copying a commit from one branch to another ................................................................................ 83
Section 17.2: Copying a range of commits from one branch to another .............................................................. 83
Section 17.3: Checking if a cherry-pick is required ................................................................................................... 84
Section 17.4: Find commits yet to be applied to upstream ..................................................................................... 84
Chapter 18: Recovering ............................................................................................................................................ 85
Section 18.1: Recovering from a reset ....................................................................................................................... 85
Section 18.2: Recover from git stash ......................................................................................................................... 85
Section 18.3: Recovering from a lost commit ........................................................................................................... 86
Section 18.4: Restore a deleted file after a commit ................................................................................................. 86
Section 18.5: Restore file to a previous version ........................................................................................................ 86
Section 18.6: Recover a deleted branch .................................................................................................................... 87
Chapter 19: Git Clean ................................................................................................................................................. 88
Section 19.1: Clean Interactively ................................................................................................................................. 88
Section 19.2: Forcefully remove untracked files ....................................................................................................... 88
Section 19.3: Clean Ignored Files ................................................................................................................................ 88
Section 19.4: Clean All Untracked Directories ........................................................................................................... 88
Chapter 20: Using a .gitattributes file ............................................................................................................. 90
Section 20.1: Automatic Line Ending Normalization ................................................................................................ 90
Section 20.2: Identify Binary Files .............................................................................................................................. 90
Section 20.3: Prefilled .gitattribute Templates ......................................................................................................... 90
Section 20.4: Disable Line Ending Normalization .................................................................................................... 90
Chapter 21: .mailmap file: Associating contributor and email aliases ............................................ 91
Section 21.1: Merge contributers by aliases to show commit count in shortlog ................................................... 91
Chapter 22: Analyzing types of workflows .................................................................................................... 92
Section 22.1: Centralized Workflow ........................................................................................................................... 92
Section 22.2: Gitflow Workflow .................................................................................................................................. 93
Section 22.3: Feature Branch Workflow ................................................................................................................... 95
Section 22.4: GitHub Flow ........................................................................................................................................... 95
Section 22.5: Forking Workflow ................................................................................................................................. 96
Chapter 23: Pulling ..................................................................................................................................................... 97
Section 23.1: Pulling changes to a local repository .................................................................................................. 97
Section 23.2: Updating with local changes ............................................................................................................... 98
Section 23.3: Pull, overwrite local ............................................................................................................................... 98
LearnLoner.com
Section 23.4: Pull code from remote ......................................................................................................................... 98
Section 23.5: Keeping linear history when pulling ................................................................................................... 98
Section 23.6: Pull, "permission denied" ...................................................................................................................... 99
Chapter 24: Hooks ................................................................................................................................................... 100
Section 24.1: Pre-push ............................................................................................................................................... 100
Section 24.2: Verify Maven build (or other build system) before committing ................................................... 101
Section 24.3: Automatically forward certain pushes to other repositories ......................................................... 101
Section 24.4: Commit-msg ....................................................................................................................................... 102
Section 24.5: Local hooks ......................................................................................................................................... 102
Section 24.6: Post-checkout ..................................................................................................................................... 102
Section 24.7: Post-commit ........................................................................................................................................ 103
Section 24.8: Post-receive ........................................................................................................................................ 103
Section 24.9: Pre-commit ......................................................................................................................................... 103
Section 24.10: Prepare-commit-msg ....................................................................................................................... 103
Section 24.11: Pre-rebase .......................................................................................................................................... 103
Section 24.12: Pre-receive ......................................................................................................................................... 104
Section 24.13: Update ................................................................................................................................................ 104
Chapter 25: Cloning Repositories ..................................................................................................................... 105
Section 25.1: Shallow Clone ...................................................................................................................................... 105
Section 25.2: Regular Clone ..................................................................................................................................... 105
Section 25.3: Clone a specific branch ..................................................................................................................... 105
Section 25.4: Clone recursively ................................................................................................................................ 106
Section 25.5: Clone using a proxy ........................................................................................................................... 106
Chapter 26: Stashing ............................................................................................................................................... 107
Section 26.1: What is Stashing? ................................................................................................................................ 107
Section 26.2: Create stash ........................................................................................................................................ 108
Section 26.3: Apply and remove stash .................................................................................................................... 109
Section 26.4: Apply stash without removing it ....................................................................................................... 109
Section 26.5: Show stash .......................................................................................................................................... 109
Section 26.6: Partial stash ........................................................................................................................................ 109
Section 26.7: List saved stashes .............................................................................................................................. 110
Section 26.8: Move your work in progress to another branch ............................................................................. 110
Section 26.9: Remove stash ..................................................................................................................................... 110
Section 26.10: Apply part of a stash with checkout ............................................................................................... 110
Section 26.11: Recovering earlier changes from stash .......................................................................................... 110
Section 26.12: Interactive Stashing .......................................................................................................................... 111
Section 26.13: Recover a dropped stash ................................................................................................................. 111
Chapter 27: Subtrees .............................................................................................................................................. 113
Section 27.1: Create, Pull, and Backport Subtree ................................................................................................... 113
Chapter 28: Renaming ........................................................................................................................................... 114
Section 28.1: Rename Folders .................................................................................................................................. 114
Section 28.2: rename a local and the remote branch .......................................................................................... 114
Section 28.3: Renaming a local branch .................................................................................................................. 114
Chapter 29: Pushing ................................................................................................................................................. 115
Section 29.1: Push a specific object to a remote branch ....................................................................................... 115
Section 29.2: Push ..................................................................................................................................................... 116
Section 29.3: Force Pushing ..................................................................................................................................... 117
Section 29.4: Push tags ............................................................................................................................................. 117
Section 29.5: Changing the default push behavior ................................................................................................ 117
LearnLoner.com
Chapter 30: Internals .............................................................................................................................................. 119
Section 30.1: Repo ..................................................................................................................................................... 119
Section 30.2: Objects ................................................................................................................................................ 119
Section 30.3: HEAD ref .............................................................................................................................................. 119
Section 30.4: Refs ...................................................................................................................................................... 119
Section 30.5: Commit Object .................................................................................................................................... 120
Section 30.6: Tree Object ......................................................................................................................................... 121
Section 30.7: Blob Object .......................................................................................................................................... 121
Section 30.8: Creating new Commits ...................................................................................................................... 122
Section 30.9: Moving HEAD ...................................................................................................................................... 122
Section 30.10: Moving refs around .......................................................................................................................... 122
Section 30.11: Creating new Refs .............................................................................................................................. 122
Chapter 31: git-tfs ..................................................................................................................................................... 123
Section 31.1: git-tfs clone ........................................................................................................................................... 123
Section 31.2: git-tfs clone from bare git repository ............................................................................................... 123
Section 31.3: git-tfs install via Chocolatey ............................................................................................................... 123
Section 31.4: git-tfs Check In ..................................................................................................................................... 123
Section 31.5: git-tfs push ........................................................................................................................................... 123
Chapter 32: Empty directories in Git ............................................................................................................... 124
Section 32.1: Git doesn't track directories ............................................................................................................... 124
Chapter 33: git-svn ................................................................................................................................................... 125
Section 33.1: Cloning the SVN repository ................................................................................................................ 125
Section 33.2: Pushing local changes to SVN .......................................................................................................... 125
Section 33.3: Working locally ................................................................................................................................... 125
Section 33.4: Getting the latest changes from SVN ............................................................................................... 126
Section 33.5: Handling empty folders ..................................................................................................................... 126
Chapter 34: Archive ................................................................................................................................................. 127
Section 34.1: Create an archive of git repository ................................................................................................... 127
Section 34.2: Create an archive of git repository with directory prefix ............................................................... 127
Section 34.3: Create archive of git repository based on specific branch, revision, tag or directory ................ 128
Chapter 35: Rewriting history with filter-branch ..................................................................................... 129
Section 35.1: Changing the author of commits ...................................................................................................... 129
Section 35.2: Setting git committer equal to commit author ............................................................................... 129
Chapter 36: Migrating to Git ............................................................................................................................... 130
Section 36.1: SubGit ................................................................................................................................................... 130
Section 36.2: Migrate from SVN to Git using Atlassian conversion utility ........................................................... 130
Section 36.3: Migrating Mercurial to Git .................................................................................................................. 131
Section 36.4: Migrate from Team Foundation Version Control (TFVC) to Git .................................................... 131
Section 36.5: Migrate from SVN to Git using svn2git ............................................................................................. 132
Chapter 37: Show ...................................................................................................................................................... 133
Section 37.1: Overview ............................................................................................................................................... 133
Chapter 38: Resolving merge conflicts ......................................................................................................... 134
Section 38.1: Manual Resolution ............................................................................................................................... 134
Chapter 39: Bundles ................................................................................................................................................ 135
Section 39.1: Creating a git bundle on the local machine and using it on another ............................................ 135
Chapter 40: Display commit history graphically with Gitk ................................................................. 136
Section 40.1: Display commit history for one file ................................................................................................... 136
Section 40.2: Display all commits between two commits ..................................................................................... 136
Section 40.3: Display commits since version tag ................................................................................................... 136
LearnLoner.com
Chapter 41: Bisecting/Finding faulty commits ......................................................................................... 137
Section 41.1: Binary search (git bisect) .................................................................................................................... 137
Section 41.2: Semi-automatically find a faulty commit ......................................................................................... 137
Chapter 42: Blaming ............................................................................................................................................... 139
Section 42.1: Only show certain lines ....................................................................................................................... 139
Section 42.2: To find out who changed a file ......................................................................................................... 139
Section 42.3: Show the commit that last modified a line ...................................................................................... 140
Section 42.4: Ignore whitespace-only changes ..................................................................................................... 140
Chapter 43: Git revisions syntax ....................................................................................................................... 141
Section 43.1: Specifying revision by object name .................................................................................................. 141
Section 43.2: Symbolic ref names: branches, tags, remote-tracking branches ................................................. 141
Section 43.3: The default revision: HEAD ................................................................................................................ 141
Section 43.4: Reflog references: <refname>@{<n>} ............................................................................................. 141
Section 43.5: Reflog references: <refname>@{<date>} ........................................................................................ 142
Section 43.6: Tracked / upstream branch: <branchname>@{upstream} .......................................................... 142
Section 43.7: Commit ancestry chain: <rev>^, <rev>~<n>, etc ............................................................................... 142
Section 43.8: Dereferencing branches and tags: <rev>^0, <rev>^{<type>} ........................................................ 143
Section 43.9: Youngest matching commit: <rev>^{/<text>}, :/<text> ................................................................... 143
Chapter 44: Worktrees ......................................................................................................................................... 145
Section 44.1: Using a worktree ................................................................................................................................. 145
Section 44.2: Moving a worktree ............................................................................................................................. 145
Chapter 45: Git Remote ........................................................................................................................................ 147
Section 45.1: Display Remote Repositories ............................................................................................................. 147
Section 45.2: Change remote url of your Git repository ....................................................................................... 147
Section 45.3: Remove a Remote Repository .......................................................................................................... 148
Section 45.4: Add a Remote Repository ................................................................................................................. 148
Section 45.5: Show more information about remote repository ......................................................................... 148
Section 45.6: Rename a Remote Repository ......................................................................................................... 149
Chapter 46: Git Large File Storage (LFS) ..................................................................................................... 150
Section 46.1: Declare certain file types to store externally ................................................................................... 150
Section 46.2: Set LFS config for all clones .............................................................................................................. 150
Section 46.3: Install LFS ............................................................................................................................................ 150
Chapter 47: Git Patch ............................................................................................................................................. 151
Section 47.1: Creating a patch .................................................................................................................................. 151
Section 47.2: Applying patches ................................................................................................................................ 152
Chapter 48: Git statistics ...................................................................................................................................... 153
Section 48.1: Lines of code per developer .............................................................................................................. 153
Section 48.2: Listing each branch and its last revision's date .............................................................................. 153
Section 48.3: Commits per developer ..................................................................................................................... 153
Section 48.4: Commits per date .............................................................................................................................. 154
Section 48.5: Total number of commits in a branch ............................................................................................. 154
Section 48.6: List all commits in pretty format ...................................................................................................... 154
Section 48.7: Find All Local Git Repositories on Computer ................................................................................... 154
Section 48.8: Show the total number of commits per author .............................................................................. 154
Chapter 49: git send-email .................................................................................................................................. 155
Section 49.1: Use git send-email with Gmail ........................................................................................................... 155
Section 49.2: Composing .......................................................................................................................................... 155
Section 49.3: Sending patches by mail ................................................................................................................... 155
Chapter 50: Git GUI Clients .................................................................................................................................. 157
LearnLoner.com
Section 50.1: gitk and git-gui .................................................................................................................................... 157
Section 50.2: GitHub Desktop .................................................................................................................................. 158
Section 50.3: Git Kraken ........................................................................................................................................... 159
Section 50.4: SourceTree .......................................................................................................................................... 159
Section 50.5: Git Extensions ...................................................................................................................................... 159
Section 50.6: SmartGit .............................................................................................................................................. 159
Chapter 51: Reflog - Restoring commits not shown in git log ........................................................... 160
Section 51.1: Recovering from a bad rebase .......................................................................................................... 160
Chapter 52: TortoiseGit ......................................................................................................................................... 161
Section 52.1: Squash commits .................................................................................................................................. 161
Section 52.2: Assume unchanged ........................................................................................................................... 162
Section 52.3: Ignoring Files and Folders ................................................................................................................. 164
Section 52.4: Branching ............................................................................................................................................ 165
Chapter 53: External merge and ditools ................................................................................................... 167
Section 53.1: Setting up KDi3 as merge tool ........................................................................................................ 167
Section 53.2: Setting up KDi3 as di tool ............................................................................................................. 167
Section 53.3: Setting up an IntelliJ IDE as merge tool (Windows) ....................................................................... 167
Section 53.4: Setting up an IntelliJ IDE as di tool (Windows) ............................................................................. 167
Section 53.5: Setting up Beyond Compare ............................................................................................................. 168
Chapter 54: Update Object Name in Reference ...................................................................................... 169
Section 54.1: Update Object Name in Reference ................................................................................................... 169
Chapter 55: Git Branch Name on Bash Ubuntu ........................................................................................ 170
Section 55.1: Branch Name in terminal ................................................................................................................... 170
Chapter 56: Git Client-Side Hooks .................................................................................................................... 171
Section 56.1: Git pre-push hook ................................................................................................................................ 171
Section 56.2: Installing a Hook ................................................................................................................................. 172
Chapter 57: Git rerere ............................................................................................................................................ 173
Section 57.1: Enabling rerere .................................................................................................................................... 173
Chapter 58: Change git repository name .................................................................................................... 174
Section 58.1: Change local setting ........................................................................................................................... 174
Chapter 59: Git Tagging ........................................................................................................................................ 175
Section 59.1: Listing all available tags ..................................................................................................................... 175
Section 59.2: Create and push tag(s) in GIT ........................................................................................................... 175
Chapter 60: Tidying up your local and remote repository ................................................................. 177
Section 60.1: Delete local branches that have been deleted on the remote ...................................................... 177
Chapter 61: di-tree ................................................................................................................................................ 178
Section 61.1: See the files changed in a specific commit ....................................................................................... 178
Section 61.2: Usage ................................................................................................................................................... 178
Section 61.3: Common di options .......................................................................................................................... 178
Credits ............................................................................................................................................................................ 179
You may also like ...................................................................................................................................................... 186
LearnLoner.com
Chapter 1: Getting started with Git
Version Release Date
2.13 2017-05-10
2.12 2017-02-24
2.11.1 2017-02-02
2.11 2016-11-29
2.10.2 2016-10-28
2.10 2016-09-02
2.9 2016-06-13
2.8 2016-03-28
2.7 2015-10-04
2.6 2015-09-28
2.5 2015-07-27
2.4 2015-04-30
2.3 2015-02-05
2.2 2014-11-26
2.1 2014-08-16
2.0 2014-05-28
1.9 2014-02-14
1.8.3 2013-05-24
1.8 2012-10-21
1.7.10 2012-04-06
1.7 2010-02-13
1.6.5 2009-10-10
1.6.3 2009-05-07
1.6 2008-08-17
1.5.3 2007-09-02
1.5 2007-02-14
1.4 2006-06-10
1.3 2006-04-18
1.2 2006-02-12
1.1 2006-01-08
1.0 2005-12-21
0.99 2005-07-11
Section 1.1: Create your first repository, then add and commit
files
At the command line, first verify that you have Git installed:
git --version
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 2
which git
If nothing is returned, or the command is not recognized, you may have to install Git on your system by
downloading and running the installer. See the Git homepage for exceptionally clear and easy installation
instructions.
After installing Git, configure your username and email address. Do this before making a commit.
Once Git is installed, navigate to the directory you want to place under version control and create an empty Git
repository:
git init
This creates a hidden folder, .git, which contains the plumbing needed for Git to work.
Next, check what files Git will add to your new repository; this step is worth special care:
git status
Review the resulting list of files; you can tell Git which of the files to place into version control (avoid adding files
with confidential information such as passwords, or files that just clutter the repo):
git add <file/directory name #1> <file/directory name #2> < ... >
If all files in the list should be shared with everyone who has access to the repository, a single command will add
everything in your current directory and its subdirectories:
git add .
This will "stage" all files to be added to version control, preparing them to be committed in your first commit.
For files that you want never under version control, create and populate a file named .gitignore before running
the add command.
Commit all the files that have been added, along with a commit message:
This creates a new commit with the given message. A commit is like a save or snapshot of your entire project. You
can now push, or upload, it to a remote repository, and later you can jump back to it if necessary.
If you omit the -m parameter, your default editor will open and you can edit and save the commit message there.
Adding a remote
To add a new remote, use the git remote add command on the terminal, in the directory your repository is stored
at.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 3
NOTE: Before adding the remote you have to create the required repository in your git service, You'll be able to
push/pull commits after adding your remote.
This creates a directory called projectname on the local machine, containing all the files in the remote Git
repository. This includes source files for the project, as well as a .git sub-directory which contains the entire
history and configuration for the project.
Note:
The https version and the ssh version are equivalent. However, some hosting services such as GitHub recommend
that you use https rather than ssh.
To minimize the use of space on the remote server you create a bare repository: one which has only the .git
objects and doesn't create a working copy in the filesystem. As a bonus you set this remote as an upstream server
to easily share updates with other programmers.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 4
git remote add origin ssh://username@server:/path/to/repo.git
(Note that ssh: is just one possible way of accessing the remote repository.)
Adding --set-upstream (or -u) created an upstream (tracking) reference which is used by argument-less Git
commands, e.g. git pull.
It has nothing to do with authentication when pushing to a remote repository (e.g. when pushing to a remote
repository using your GitHub, BitBucket, or GitLab account)
To declare that identity for all repositories, use git config --global
This will store the setting in your user's .gitconfig file: e.g. $HOME/.gitconfig or for Windows,
%USERPROFILE%\.gitconfig.
To declare an identity for a single repository, use git config inside a repo.
This will store the setting inside the individual repository, in the file $GIT_DIR/config. e.g.
/path/to/your/repo/.git/config.
cd /path/to/my/repo
git config user.name "Your Login At Work"
git config user.email [email protected]
Settings stored in a repository's config file will take precedence over the global config when you use that repository.
Tips: if you have different identities (one for open-source project, one at work, one for private repos, ...), and you
don't want to forget to set the right one for each different repos you are working on:
Version ≥ 2.8
To force git to look for your identity only within a repository's settings, not in the global config:
That way, if you forget to set your user.name and user.email for a given repository and try to make a commit, you
will see:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 5
no name was given and auto-detection is disabled
no email was given and auto-detection is disabled
$ git remote -v
origin https://github.com/myusername/repo.git (fetch)
origin https://github.com/myusername/repo.git (push)
upstream # this line may or may not be here
If upstream is there already (it is on some Git versions) you need to set the URL (currently it's empty):
If the upstream is not there, or if you also want to add a friend/colleague's fork (currently they do not exist):
For example, to get all available information about the git diff command, use:
Similarly, to get all available information about the status command, use:
If you only want a quick help showing you the meaning of the most used command line flags, use -h:
git checkout -h
Before you generate an SSH key, you can check to see if you have any existing SSH keys.
$ ls -al ~/.ssh
# Lists all the files in your ~/.ssh directory
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 6
Check the directory listing to see if you already have a public SSH key. By default the filenames of the public keys
are one of the following:
id_dsa.pub
id_ecdsa.pub
id_ed25519.pub
id_rsa.pub
If you see an existing public and private key pair listed that you would like to use on your Bitbucket, GitHub (or
similar) account you can copy the contents of the id_*.pub file.
If not, you can create a new public and private key pair with the following command:
$ ssh-keygen
Press the Enter or Return key to accept the default location. Enter and re-enter a passphrase when prompted, or
leave it empty.
Ensure your SSH key is added to the ssh-agent. Start the ssh-agent in the background if it's not already running:
Add you SSH key to the ssh-agent. Notice that you'll need te replace id_rsa in the command with the name of your
private key file:
$ ssh-add ~/.ssh/id_rsa
If you want to change the upstream of an existing repository from HTTPS to SSH you can run the following
command:
In order to clone a new repository over SSH you can run the following command:
If you can, it’s generally useful to install Git from source, because you’ll get the most recent version. Each version of
Git tends to include useful UI enhancements, so getting the latest version is often the best route if you feel
comfortable compiling software from source. It is also the case that many Linux distributions contain very old
packages; so unless you’re on a very up-to-date distro or are using backports, installing from source may be the
best bet.
To install Git, you need to have the following libraries that Git depends on: curl, zlib, openssl, expat, and libiconv.
For example, if you’re on a system that has yum (such as Fedora) or apt-get (such as a Debian based system), you
can use one of these commands to install all of the dependencies:
When you have all the necessary dependencies, you can go ahead and grab the latest snapshot from the Git web
site:
After this is done, you can also get Git via Git itself for updates:
Installing on Linux
If you want to install Git on Linux via a binary installer, you can generally do so through the basic package-
management tool that comes with your distribution. If you’re on Fedora, you can use yum:
Installing on Mac
There are three easy ways to install Git on a Mac. The easiest is to use the graphical Git installer, which you can
download from the SourceForge page.
http://sourceforge.net/projects/git-osx-installer/
Figure 1-7. Git OS X installer. The other major way is to install Git via MacPorts (http://www.macports.org). If you
have MacPorts installed, install Git via
You don’t have to add all the extras, but you’ll probably want to include +svn in case you ever have to use Git with
Subversion repositories (see Chapter 8).
Homebrew (http://brew.sh/) is another alternative to install Git. If you have Homebrew installed, install Git via
Installing on Windows
Installing Git on Windows is very easy. The msysGit project has one of the easier installation procedures. Simply
download the installer exe file from the GitHub page, and run it:
http://msysgit.github.io
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 8
After it’s installed, you have both a command-line version (including an SSH client that will come in handy later) and
the standard GUI.
Note on Windows usage: you should use Git with the provided msysGit shell (Unix style), it allows to use the complex
lines of command given in this book. If you need, for some reason, to use the native Windows shell / command line
console, you have to use double quotes instead of single quotes (for parameters with spaces in them) and you must
quote the parameters ending with the circumflex accent (^) if they are last on the line, as it is a continuation symbol
in Windows.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 9
Chapter 2: Browsing the history
Parameter Explanation
-q, --quiet Quiet, suppresses diff output
--source Shows source of commit
--use-mailmap Use mail map file (changes user info for committing user)
--decorate[=...] Decorate options
Show log for specific range of lines in a file, counting from 1. Starts from line n, goes to line
--L <n,m:file>
m. Also shows diff.
--show-signature Display signatures of signed commits
-i, --regexp-ignore-case Match the regular expression limiting patterns without regard to letter case
will display all your commits with the author and hash. This will be shown over multiple lines per commit. (If you
wish to show a single line per commit, look at onelineing). Use the q key to exit the log.
By default, with no arguments, git log lists the commits made in that repository in reverse chronological
order – that is, the most recent commits show up first. As you can see, this command lists each commit
with its SHA-1 checksum, the author’s name and email, the date written, and the commit message. -
source
commit 87ef97f59e2a2f4dc425982f76f14a57d0900bcf
Merge: e50ff0d eb8b729
Author: Brian
Date: Thu Mar 24 15:52:07 2016 -0700
commit eb8b7298d516ea20a4aadb9797c7b6fd5af27ea5
Author: BKinahan
Date: Thu Mar 24 21:11:36 2016 +0000
commit e50ff0d249705f41f55cd435f317dcfd02590ee7
Merge: 6b01875 2652d04
Author: Mrugesh Mohapatra
Date: Thu Mar 24 14:26:04 2016 +0530
If you wish to limit your command to last n commits log you can simply pass a parameter. For example, if you wish
to list last 2 commits logs
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 10
git log -2
sample output :
The format option allows you to specify your own log output format:
Parameter Details
%C(color_name) option colors the output that comes after it
%h or %H abbreviates commit hash (use %H for complete hash)
%Creset resets color to default terminal color
%d ref names
%s subject [commit message]
%cr committer date, relative to current date
%an author name
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 11
will show all of your commits with only the first part of the hash and the commit message. Each commit will be in a
single line, as the oneline flag suggests.
The oneline option prints each commit on a single line, which is useful if you’re looking at a lot of
commits. - source
Example (from Free Code Camp repository, with the same section of code from the other example):
If you wish to limit you command to last n commits log you can simply pass a parameter. For example, if you wish
to list last 2 commits logs
Searches for addition or removal of specific string or the string matching provided REGEXP. In this case we're
looking for addition/removal of the string #define SAMPLES. For example:
or
Searches for changes in lines containing specific string or the string matching provided REGEXP. For example:
If no parameters are given, a list of all commits made per committer will be shown in chronological order.
$ git shortlog
Committer 1 (<number_of_commits>):
Commit Message 1
Commit Message 2
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 12
...
Committer 2 (<number_of_commits>):
Commit Message 1
Commit Message 2
...
To simply see the number of commits and suppress the commit description, pass in the summary option:
-s
--summary
$ git shortlog -s
<number_of_commits> Committer 1
<number_of_commits> Committer 2
To sort the output by number of commits instead of alphabetically by committer name, pass in the numbered
option:
-n
--numbered
-e
A custom format option can also be provided if you want to display information other than the commit subject:
--format
This can be any string accepted by the --format option of git log.
Example:
Will search for removed file string in all logs in all branches.
Starting from git 2.4+, the search can be inverted using the --invert-grep option.
Example:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 13
Section 2.8: Log for a range of lines within a file
$ git log -L 1,20:index.html
commit 6a57fde739de66293231f6204cbd8b2feca3a869
Author: John Doe <[email protected]>
Date: Tue Mar 22 16:33:42 2016 -0500
commit message
As with other commands and flags that accept a date parameter, the allowed date format is as supported by GNU
date (highly flexible).
ommit 8ea1452aca481a837d9504f1b2c77ad013367d25
Author: Raymond Chou <[email protected]>
Date: Wed Mar 2 10:35:25 2016 -0800
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 14
diff --git a/README.md b/README.md
index 1120a00..9bef0ce 100644
--- a/README.md
+++ b/README.md
@@ -134,7 +134,7 @@ the control function threw, but *after* testing the other functions and
readying
the logging. The criteria for matching errors is based on the constructor and
message.
## Asynchronous behaviors
commit d3178a22716cc35b6a2bdd679a7ec24bc8c63ffa
:
Example:
commit 4ded994d7fc501451fa6e233361887a2365b91d1
Author: Manassés Souza <[email protected]>
Date: Mon Jun 6 21:32:30 2016 -0300
mltracking-poc/.gitignore | 1 +
mltracking-poc/pom.xml | 14 ++++++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
commit 506fff56190f75bc051248770fb0bcd976e3f9a5
Author: Manassés Souza <[email protected]>
Date: Sat Jun 4 12:35:16 2016 -0300
.gitignore | 42
++++++++++++
mltracking-poc/mvnw | 233
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
mltracking-poc/mvnw.cmd | 145
+++++++++++++++++++++++++++++++++++++++
mltracking-poc/pom.xml | 74
++++++++++++++++++++
mltracking-poc/src/main/java/br/com/mls/mltracking/MltrackingPocApplication.java | 12 ++++
mltracking-poc/src/main/resources/application.properties | 0
mltracking-poc/src/test/java/br/com/mls/mltracking/MltrackingPocApplicationTests.java | 18 +++++
7 files changed, 524 insertions(+)
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 15
git show 48c83b3690dfc7b0e622fd220f8f37c26a77c934
Example
commit 48c83b3690dfc7b0e622fd220f8f37c26a77c934
Author: Matt Clark <[email protected]>
Date: Wed May 4 18:26:40 2016 -0400
Section 2.14: One line showing commiter name and time since
commit
tree = log --oneline --decorate --source --pretty=format:'"%Cblue %h %Cgreen %ar %Cblue %an
%C(yellow) %d %Creset %s"' --all --graph
example
* 40554ac 3 months ago Alexander Zolotov Merge pull request #95 from
gmandnepr/external_plugins
|\
| * e509f61 3 months ago Ievgen Degtiarenko Documenting new property
| * 46d4cb6 3 months ago Ievgen Degtiarenko Running idea with external plugins
| * 6253da4 3 months ago Ievgen Degtiarenko Resolve external plugin classes
| * 9fdb4e7 3 months ago Ievgen Degtiarenko Keep original artifact name as this may be
important for intellij
| * 22e82e4 3 months ago Ievgen Degtiarenko Declaring external plugin in intellij section
|/
* bc3d2cb 3 months ago Alexander Zolotov Ignore DTD in plugin.xml
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 16
Chapter 3: Working with Remotes
Section 3.1: Deleting a Remote Branch
To delete a remote branch in Git:
or
git remote -v
# origin https://github.com/username/repo.git (fetch)
# origin https://github.com/usernam/repo.git (push)
git remote -v
# origin https://github.com/username/repo2.git (fetch)
# origin https://github.com/username/repo2.git (push)
git remote
List all the existing remotes associated with this repository in detail including the fetch and push URLs:
or simply
git remote -v
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 17
git fetch [remote-name] --prune
git pull
The pull with --rebase flag command combines a fetch and a rebase instead of merge.
You will see sometimes refs/tags/v0.1.6 and refs/tags/v0.1.6^{}: the ^{} to list the dereferenced annotated
tag (ie the commit that tag is pointing to)
Since git 2.8 (March 2016), you can avoid that double entry for a tag, and list directly those dereferenced tags with:
It can also help resolve the actual url used by a remote repo when you have "url.<base>.insteadOf" config setting.
If git remote --get-url <aremotename> returns https://server.com/user/repo, and you have set git config
url.ssh://[email protected]:.insteadOf https://server.com/:
Adds remote git repository represented by git-repository-url as new remote named upstream to the git
repository
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 18
After you use git checkout to create a new branch, you will need to set that upstream origin to push to using
After that, you can use git push while you are on that branch.
Example
git remote
# origin
git remote -v
# origin https://github.com/username/repo.git (fetch)
# origin https://github.com/usernam/repo.git (push)
Rename remote
git remote -v
# destination https://github.com/username/repo.git (fetch)
# destination https://github.com/usernam/repo.git (push)
This error means that the remote you tried the old remote name (origin) doesn't exist.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 19
2. Remote [new name] already exists.
With 2.7+, it is also possible to do, which is arguably better than the above one that uses the config command.
Example:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 20
Chapter 4: Staging
Section 4.1: Staging All Changes to Files
git add -A
Version ≥ 2.0
git add .
In version 2.x, git add . will stage all changes to files in the current directory and all its subdirectories. However, in
1.x it will only stage new and modified files, not deleted files.
Use git add -A, or its equivalent command git add --all, to stage all changes to files in any version of git.
git add -p
or
This opens an interactive prompt that allows you to look at the diffs and let you decide whether you want to include
them or not.
This makes it easy to catch changes which you do not want to commit.
You can also open this via git add --interactive and selecting p.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 21
Section 4.4: Interactive add
git add -i (or --interactive) will give you an interactive interface where you can edit the index, to prepare what
you want to have in the next commit. You can add and remove changes to whole files, add untracked files and
remove files from being tracked, but also select subsection of changes to put in the index, by selecting chunks of
changes to be added, splitting those chunks, or even editing the diff. Many graphical commit tools for Git (like e.g.
git gui) include such feature; this might be easier to use than the command line version.
It is very useful (1) if you have entangled changes in the working directory that you want to put in separate commits,
and not all in one single commit (2) if you are in the middle of an interactive rebase and want to split too large
commit.
$ git add -i
staged unstaged path
1: unchanged +4/-4 index.js
2: +1/-0 nothing package.json
The top half of this output shows the current state of the index broken up into staged and unstaged columns:
1. index.js has had 4 lines added and 4 lines removed. It is currently not staged, as the current status reports
"unchanged." When this file becomes staged, the +4/-4 bit will be transferred to the staged column and the
unstaged column will read "nothing."
2. package.json has had one line added and has been staged. There are no further changes since it has been
staged as indicated by the "nothing" line under the unstaged column.
The bottom half shows what you can do. Either enter a number (1-8) or a letter (s, u, r, a, p, d, q, h).
status shows output identical to the top part of the output above.
update allows you to make further changes to the staged commits with additional syntax.
add untracked allows you to add filepaths previously untracked by version control.
patch allows for one path to be selected out of an output similar to status for further analysis.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 22
Section 4.6: Staging A Single File
To stage a file for committing, run
To delete the file from git without removing it from disk, use the --cached flag
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 23
Chapter 5: Ignoring Files and Folders
This topic illustrates how to avoid adding unwanted files (or file changes) in a Git repo. There are several ways
(global or local .gitignore, .git/exclude, git update-index --assume-unchanged, and git update-index --
skip-tree), but keep in mind Git is managing content, which means: ignoring actually ignores a folder content (i.e.
files). An empty folder would be ignored by default, since it cannot be added anyway.
In software projects, .gitignore typically contains a listing of files and/or directories that are generated during the
build process or at runtime. Entries in the .gitignore file may include names or paths pointing to:
When created in the top level directory, the rules will apply recursively to all files and sub-directories throughout
the entire repository. When created in a sub-directory, the rules will apply to that specific directory and its sub-
directories.
1. tracked by Git
2. reported by commands such as git status or git diff
3. staged with commands such as git add -A
In the unusual case that you need to ignore tracked files, special care should be taken. See: Ignore files that have
already been committed to a Git repository.
Examples
Here are some generic examples of rules in a .gitignore file, based on glob file patterns:
# Ignoring directories
# Both the directory itself and its contents will be ignored.
bin/
gen/
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 24
# Glob pattern can also be used here to ignore paths with certain characters.
# For example, the below rule will match both build/ and Build/
[bB]uild/
# Without the trailing slash, the rule will match a file and/or
# a directory, so the following would ignore both a file named `gen`
# and a directory named `gen`, as well as any contents of that directory
bin
gen
# To ignore files only at the top level directory, but not in its
# subdirectories, prefix the rule with a `/`
/*.apk
/*.class
# Use the backslash as escape character to ignore files with a hash (#)
# (supported since 1.6.2.1)
\#*#
Most .gitignore files are standard across various languages, so to get started, here is set of sample .gitignore
files listed by language from which to clone or copy/modify into your project. Alternatively, for a fresh project you
may consider auto-generating a starter file using an online tool.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 25
Other forms of .gitignore
.gitignore files are intended to be committed as part of the repository. If you want to ignore certain files without
committing the ignore rules, here are some options:
Edit the .git/info/exclude file (using the same syntax as .gitignore). The rules will be global in the scope
of the repository;
Set up a global gitignore file that will apply ignore rules to all your local repositories:
Furthermore, you can ignore local changes to tracked files without changing the global git configuration with:
See more details on differences between the latter flags and the git update-index documentation for further
options.
Note: -X (caps) cleans up only ignored files. Use -x (no caps) to also remove untracked files.
You can pass filenames on the command line, and git check-ignore will list the filenames that are ignored. For
example:
$ cat .gitignore
*.o
$ git check-ignore example.o Readme.md
example.o
Here, only *.o files are defined in .gitignore, so Readme.md is not listed in the output of git check-ignore.
If you want to see line of which .gitignore is responsible for ignoring a file, add -v to the git check-ignore command:
From Git 1.7.6 onwards you can also use git status --ignored in order to see ignored files. You can find more
info on this in the official documentation or in Finding files ignored by .gitignore.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 26
Section 5.3: Exceptions in a .gitignore file
If you ignore files by using a pattern but have exceptions, prefix an exclamation mark(!) to the exception. For
example:
*.txt
!important.txt
The above example instructs Git to ignore all files with the .txt extension except for files named important.txt.
folder/
!folder/*.txt
In this example all .txt files in the folder would remain ignored.
The right way is re-include the folder itself on a separate line, then ignore all files in folder by *, finally re-include
the *.txt in folder, as the following:
!folder/
folder/*
!folder/*.txt
Note: For file names beginning with an exclamation mark, add two exclamation marks or escape with the \
character:
!!includethis
\!excludethis
Git will now use this in addition to each repository's own .gitignore file. Rules for this are:
If the local .gitignore file explicitly includes a file while the global .gitignore ignores it, the local
.gitignore takes priority (the file will be included)
If the repository is cloned on multiple machines, then the global .gigignore must be loaded on all machines
or at least include it, as the ignored files will be pushed up to the repo while the PC with the global
.gitignore wouldn't update it. This is why a repo specific .gitignore is a better idea than a global one if the
project is worked on by a team
This file is a good place to keep platform, machine or user specific ignores, e.g. OSX .DS_Store, Windows Thumbs.db
or Vim *.ext~ and *.ext.swp ignores if you don't want to keep those in the repository. So one team member
working on OS X can add all .DS_STORE and _MACOSX (which is actually useless), while another team member on
Windows can ignore all thumbs.bd
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 27
a Git repository
If you have already added a file to your Git repository and now want to stop tracking it (so that it won't be present
in future commits), you can remove it from the index:
This will remove the file from the repository and prevent further changes from being tracked by Git. The --cached
option will make sure that the file is not physically deleted.
Note that previously added contents of the file will still be visible via the Git history.
Keep in mind that if anyone else pulls from the repository after you removed the file from the index, their copy
will be physically deleted.
You can make Git pretend that the working directory version of the file is up to date and read the index version
instead (thus ignoring changes in it) with "skip worktree" bit:
Writing is not affected by this bit, content safety is still first priority. You will never lose your precious ignored
changes; on the other hand this bit conflicts with stashing: to remove this bit, use
It is sometimes wrongly recommended to lie to Git and have it assume that file is unchanged without examining it.
It looks at first glance as ignoring any further changes to the file, without removing it from its index:
This will force git to ignore any change made in the file (keep in mind that if you pull any changes to this file, or you
stash it, your ignored changes will be lost)
If you want git to "care" about this file again, run the following command:
If you want to ignore certain files in a repository locally and not make the file part of any repository, edit
.git/info/exclude inside your repository.
For example:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 28
pushReports.py
server/
The above command instructs Git to assume my-file.txt hasn't been changed, and not to check or report
changes. The file is still present in the repository.
This can be useful for providing defaults and allowing local environment overrides, e.g.:
# commit to Git
git add .env
git commit -m "Adding .env template"
# no changes!
git status
If you want to ignore the file only in part of the tree, you can specify the subdirectories of a specific directory with
** pattern:
Or you can create a .gitignore file in the bar/ directory. Equivalent to the previous example would be creating file
bar/.gitignore with these contents:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 29
to your project, you can choose or generate a .gitignore file:
https://www.gitignore.io/
https://github.com/github/gitignore
Many hosting services such as GitHub and BitBucket offer the ability to generate .gitignore files based upon the
programming languages and IDEs you may be using:
examples/
output.log
src/
<files not shown>
output.log
README.md
output.log in the examples directory is valid and required for the project to gather an understanding while the one
beneath src/ is created while debugging and should not be in the history or part of the repository.
There are two ways to ignore this file. You can place an absolute path into the .gitignore file at the root of the
working directory:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 30
# /.gitignore
src/output.log
Alternatively, you can create a .gitignore file in the src/ directory and ignore the file that is relative to this
.gitignore:
# /src/.gitignore
output.log
One hack to get around this is to use a .gitkeep file to register the folder for Git. To do this, just create the required
directory and add a .gitkeep file to the folder. This file is blank and doesn't serve any purpose other than to just
register the folder. To do this in Windows (which has awkward file naming conventions) just open git bash in the
directory and run the command:
$ touch .gitkeep
This command just makes a blank .gitkeep file in the current directory
Another hack for this is very similar to the above and the same steps can be followed, but instead of a .gitkeep,
just use a dummy.txt instead. This has the added bonus of being able to easily create it in Windows using the
context menu. And you get to leave funny messages in them too.You can also use .gitkeep file to track the empty
directory. .gitkeep normally is an empty file that is added to track the empty directory.
.git
.gitignore
./example_1
./dir/example_2
./example_2
example_2
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 31
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
.example_1
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
dir/
example_2
If you want to list recursively ignored files in directories, you have to use additional parameter - --untracked-
files=all
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
example_1
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
dir/example_2
example_2
You can make Git "unsee" those lines using clean filter. They won't even show up in diffs.
struct settings s;
s.host = "localhost";
s.port = 5653;
s.auth = 1;
s.port = 15653; // NOCOMMIT
s.debug = 1; // NOCOMMIT
s.auth = 0; // NOCOMMIT
Create "nocommit" filter by adding this to Git config file like .git/config:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 32
[filter "nocommit"]
clean=grep -v NOCOMMIT
file1.c filter=nocommit
Caveats:
You can add this snippet to your global git config to have more convenient git hide, git unhide and git hidden
commands:
[alias]
hide = update-index --skip-worktree
unhide = update-index --no-skip-worktree
hidden = "!git ls-files -v | grep ^[hsS] | cut -c 3-"
You can also use the option --assume-unchanged with the update-index function
If you want to watch this file again for the changes, use
When --assume-unchanged flag is specified, the user promises not to change the file and allows Git to assume that
the working tree file matches what is recorded in the index.Git will fail in case it needs to modify this file in the
index e.g. when merging in a commit; thus, in case the assumed-untracked file is changed upstream, you will need
to handle the situation manually.The focus lies on performance in this case.
While --skip-worktree flag is useful when you instruct git not to touch a specific file ever because the file is going to
be changed locally and you don't want to accidentally commit the changes (i.e configuration/properties file
configured for a particular environment). Skip-worktree takes precedence over assume-unchanged when both are
set.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 33
Section 5.15: Clear already committed files, but included in
.gitignore
Sometimes it happens that a file was being tracked by git, but in a later point in time was added to .gitignore, in
order to stop tracking it. It's a very common scenario to forget to clean up such files before its addition to .gitignore.
In this case, the old file will still be hanging around in the repository.
To fix this problem, one could perform a "dry-run" removal of everything in the repository, followed by re-adding all
the files back. As long as you don't have pending changes and the --cached parameter is passed, this command is
fairly safe to run:
# Remove everything from the index (the files will stay in the file system)
$ git rm -r --cached .
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 34
Chapter 6: Git Di
Parameter Details
-p, -u, --patch Generate patch
Suppress diff output. Useful for commands like git show that show the patch by default, or to
-s, --no-patch
cancel the effect of --patch
--raw Generate the diff in raw format
--diff-algorithm= Choose a diff algorithm. The variants are as follows: myers, minimal, patience, histogram
Output a condensed summary of extended header information such as creations, renames and
--summary
mode changes
--name-only Show only names of changed files
Show names and statuses of changed files The most common statuses are M (Modified), A
--name-status
(Added), and D (Deleted)
Warn if changes introduce conflict markers or whitespace errors. What are considered whitespace
errors is controlled by core.whitespace configuration. By default, trailing whitespaces (including
--check lines that solely consist of whitespaces) and a space character that is immediately followed by a
tab character inside the initial indent of the line are considered whitespace errors. Exits with non-
zero status if problems are found. Not compatible with --exit-code
Instead of the first handful of characters, show the full pre- and post-image blob object names on
--full-index
the "index" line when generating patch format output
--binary In addition to --full-index, output a binary diff that can be applied with git apply
-a, --text Treat all files as text.
Set the color mode; i.e. use --color=always if you would like to pipe a diff to less and keep git's
--color
coloring
This will show the unstaged changes on the current branch from the commit before it. It will only show changes
relative to the index, meaning it shows what you could add to the next commit, but haven't. To add (stage) these
changes, you can use git add.
If a file is staged, but was modified after it was staged, git diff will show the differences between the current file
and the staged version.
This will show the textual difference between the commits, regardless of where they are in the tree.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 35
This will show the changes between the previous commit and the currently staged files.
NOTE: You can also use the following commands to accomplish the same thing:
git status -v
is equivalent to
The difference being that the output of the latter will actually tell you which changes are staged for commit and
which are not.
Shows the changes between the previous commit of the specified file (myfile.txt) and the locally-modified version
that has not yet been staged.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 36
The above shows the changes between the previous commit of all files in the specified directory (documentation/)
and the locally-modified versions of these files, that have not yet been staged.
To show the difference between some version of a file in a given commit and the local HEAD version you can specify
the commit you want to compare against:
To show the difference between the version specified by the hash ada9b57 and the latest commit on the branch
my_branchname for only the relative directory called my_changed_directory/ you can do this:
Rather than displaying lines changed, this will display differences within lines. For example, rather than:
-Hello world
+Hello world!
Where the whole line is marked as changed, word-diff alters the output to:
Hello [-world-]{+world!+}
You can omit the markers [-, -], {+, +} by specifying --word-diff=color or --color-words. This will only use color
coding to mark the difference:
This will show the changes between the previous commit and the current commit.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 37
Section 6.10: dierence between two commit or branch
To view difference between two branch
Section 6.12: Di UTF-16 encoded text and binary plist files
You can diff UTF-16 encoded files (localization strings file os iOS and macOS are examples) by specifying how git
should diff these files.
[diff "utf16"]
textconv = "iconv -f utf-16 -t utf-8"
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 38
Then edit or create a .gitattributes file in the root of the repository where you want to use it. Or just edit
~/.gitattributes.
*.strings diff=utf16
This will convert all files ending in .strings before git diffs.
You can do similar things for other files, that can be converted to text.
[diff "plist"]
textconv = plutil -convert xml1 -o -
and .gitattributes
*.plist diff=plist
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 39
Chapter 7: Undoing
Section 7.1: Return to a previous commit
To jump back to a previous commit, first find the commit's hash using git log.
This places you at commit 789abcd. You can now make new commits on top of this old commit without affecting the
branch your head is on. Any changes can be made into a proper branch using either branch or checkout -b.
Beware: While you can recover the discarded commits using reflog and reset, uncommitted changes cannot be
recovered. Use git stash; git reset instead of git reset --hard to be safe.
Used over all file paths, recursively from the current directory, it will undo all changes in the working copy.
git checkout -- .
To only undo parts of the changes use --patch. You will be asked, for each change, if it should be undone or not.
With local commits that you have yet to push to a remote you can also do a soft reset. You can thus rework the files
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 40
and then the commits.
The above example would unwind your last two commits and return the files to your working copy. You could then
make further changes and new commits.
Beware: All of these operations, apart from soft resets, will permanently delete your changes. For a safer option,
use git stash -p or git stash, respectively. You can later undo with stash pop or delete forever with stash drop.
$ git reflog
4a5cbb3 HEAD@{0}: rebase finished: returning to refs/heads/foo
4a5cbb3 HEAD@{1}: rebase: fixed such and such
904f7f0 HEAD@{2}: rebase: checkout upstream/master
3cbe20a HEAD@{3}: commit: fixed such and such
...
You can see the commit before the rebase was HEAD@{3} (you can also checkout the hash):
Now you create a new branch / delete the old one / try the rebase again.
You can also reset directly back to a point in your reflog, but only do this if you're 100% sure it's what you want to
do:
This will set your current git tree to match how it was at that point (See Undoing Changes).
This can be used if you're temporarily seeing how well a branch works when rebased on another branch, but you
don't want to keep the results.
If you haven't yet pushed your merge to the remote repository then you can follow the same procedure as in undo
the commit although there are some subtle differences.
A reset is the simplest option as it will undo both the merge commit and any commits added from the branch.
However, you will need to know what SHA to reset back to, this can be tricky as your git log will now show
commits from both branches. If you reset to the wrong commit (e.g. one on the other branch) it can destroy
committed work.
> git reset --hard <last commit from the branch you are on>
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 41
> git reset HEAD~
A revert is safer, in that it won't destroy committed work, but involves more work as you have to revert the revert
before you can merge the branch back in again (see the next section).
Afterwards you discover that the feature you just merged in broke the system for other developers, it must be
undone right away, and fixing the feature itself will take too long so you simply want to undo the merge.
At this point the gremlins are out of the system and your fellow developers have stopped yelling at you. However,
we are not finished just yet. Once you fix the problem with the add-gremlins feature you will need to undo this
revert before you can merge back in.
At this point your feature is now successfully added. However, given that bugs of this type are often introduced by
merge conflicts a slightly different workflow is sometimes more helpful as it lets you fix the merge conflict on your
branch.
Don't use git push --force unless you wish to bring down the opprobrium of all other users of that repository.
Never rewrite public history.
If, for example, you've just pushed up a commit that contains a bug and you need to back it out, do the following:
Now you are free to revert the revert commit locally, fix your code, and push the good code:
If the commit you want to revert is already further back in the history, you can simply pass the commit hash. Git will
create a counter-commit undoing your original commit, which you can push to your remote safely.
-i puts rebase in "interactive mode". It starts off like the rebase discussed above, but before replaying any commits,
it pauses and allows you to gently modify each commit as it's replayed.rebase -i will open in your default text
editor, with a list of commits being applied, like this:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 43
To drop a commit, just delete that line in your editor. If you no longer want the bad commits in your project, you
can delete lines 1 and 3-4 above.If you want to combine two commits together, you can use the squash or fixup
commands
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 44
Chapter 8: Merging
Parameter Details
-m Message to be included in the merge commit
-v Show verbose output
--abort Attempt to revert all files back to their state
--ff-only Aborts instantly when a merge-commit would be required
--no-ff Forces creation of a merge-commit, even if it wasn't mandatory
--no-commit Pretends the merge failed to allow inspection and tweaking of the result
--stat Show a diffstat after merge completion
-n/--no-stat Don't show the diffstat
--squash Allows for a single commit on the current branch with the merged changes
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 45
$ git checkout --ours -- file1.txt # Use our version of file1, delete all their changes
$ git checkout --theirs -- file2.txt # Use their version of file2, delete all our changes
This merges the branch incomingBranch into the branch you are currently in. For example, if you are currently in
master, then incomingBranch will be merged into master.
Merging can create conflicts in some cases. If this happens, you will see the message Automatic merge failed;
fix conflicts and then commit the result. You will need to manually edit the conflicted files, or to undo your
merge attempt, run:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 46
Chapter 9: Submodules
Section 9.1: Cloning a Git repository having submodules
When you clone a repository that uses submodules, you'll need to initialize and update them.
This will clone the referenced submodules and place them in the appropriate folders (including submodules within
submodules). This is equivalent to running git submodule update --init --recursive immediately after the
clone is finished.
Sometimes instead of using the state that is referenced you want to update to your local checkout to the latest
state of that submodule on a remote. To check out all submodules to the latest state on the remote with a single
command, you can use
Note that this will just update your local working copy. Running git status will list the submodule directory as dirty
if it changed because of this command. To update your repository to reference the new state instead, you have to
commit the changes:
There might be some changes you have that can have merge conflict if you use git pull so you can use git pull
--rebase to rewind your changes to top, most of the time it decreases the chances of conflict. Also it pulls all the
branches to local.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 47
You should add and commit the new .gitmodules file; this tells Git what submodules should be cloned when git
submodule update is run.
But one can request to update that submodule to the latest commit of a branch of the submodule remote repo.
Rather than going in each submodule, doing a git checkout abranch --track origin/abranch, git pull, you
can simply do (from the parent repo) a:
Since the SHA1 of the submodule would change, you would still need to follow that with:
git add .
git commit -m "update submodules"
cd /path/to/parent/repo
git config -f .gitmodules submodule.asubmodule.branch abranch
Run:
1. Edit .gitmodules and change the path of the submodule appropriately, and put it in the index with git add
.gitmodules.
2. If needed, create the parent directory of the new location of the submodule (mkdir -p /path/to).
3. Move all content from the old to the new directory (mv -vi /path/to/module new/path/to/submodule).
7. Edit the .git/modules//path/to/config file, make sure that worktree item points to the new locations, so in
this example it should be worktree = ../../../../..//path/to/module. Typically there should be two more
.. then directories in the direct path in that place. . Edit the file /path/to/module/.git, make sure that the path
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 48
in it points to the correct new location inside the main project .git folder, so in this example gitdir:
../../../.git/modules//path/to/module.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: .gitmodules
# renamed: old/path/to/submodule -> new/path/to/submodule
#
git submodule deinit the_submodule deletes the_submodules' entry from .git/config. This excludes
the_submodule from git submodule update, git submodule sync and git submodule foreach calls and
deletes its local content (source). Also, this will not be shown as change in your parent repository. git
submodule init and git submodule update will restore the submodule, again without commitable changes
in your parent repository.
git rm the_submodule will remove the submodule from the work tree. The files will be gone as well as the
submodules' entry in the .gitmodules file (source). If only git rm the_submodule (without prior git
submodule deinit the_submodule is run, however, the submodules' entry in your .git/config file will remain.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 49
Chapter 10: Committing
Parameter Details
Message to include in the commit. Specifying this parameter bypasses Git's normal
--message, -m
behavior of opening an editor.
Specify that the changes currently staged should be added (amended) to the
--amend
previous commit. Be careful, this can rewrite history!
Use the selected commit message without launching an editor. For example, git
--no-edit commit --amend --no-edit amends a commit without changing its commit
message.
--all, -a Commit all changes, including changes that aren't yet staged.
--date Manually set the date that will be associated with the commit.
Commit only the paths specified. This will not commit what you currently have
--only
staged unless told to do so.
--patch, -p Use the interactive patch selection interface to chose which changes to commit.
--help Displays the man page for git commit
-S[keyid], -S --gpg- Sign commit, GPG-sign commit, countermand commit.gpgSign configuration
sign[=keyid], -S --no-gpg-sign variable
-n, --no-verify This option bypasses the pre-commit and commit-msg hooks. See also Hooks
Commits with Git provide accountability by attributing authors with changes to code. Git offers multiple features for
the specificity and security of commits. This topic explains and demonstrates proper practices and procedures in
committing with Git.
After making changes to your source code, you should stage those changes with Git before you can commit them.
This tells git that you want to add the files to the next commit you do.
git commit
Note that this will open a text editor, which is often vim. If you are not familiar with vim, you might want to know
that you can press i to go into insert mode, write your commit message, then press Esc and :wq to save and quit. To
avoid opening the text editor, simply include the -m flag with your message
Commit messages often follow some specific formatting rules, see Good commit messages for more information.
Shortcuts
If you have changed a lot of files in the directory, rather than listing each one of them, you could use:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 50
git add --all # equivalent to "git add -a"
Or to add all changes, not including files that have been deleted, from the top-level directory and subdirectories:
git add .
git add -u
Alternately, if you have only modified existing files or deleted files, and have not created any new ones, you can
combine the actions of git add and git commit in a single command:
Note that this will stage all modified files in the same way as git add --all.
Sensitive data
You should never commit any sensitive data, such as passwords or even private keys. If this case happens and the
changes are already pushed to a central server, consider any sensitive data as compromised. Otherwise, it is
possible to remove such data afterwards. A fast and easy solution is the usage of the "BFG Repo-Cleaner":
https://rtyley.github.io/bfg-repo-cleaner/.
The command bfg --replace-text passwords.txt my-repo.git reads passwords out of the passwords.txt file
and replaces these with ***REMOVED***. This operation considers all previous commits of the entire repository.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 51
just a bit of a change // What has changed?
TASK-371 // No description at all, reader will need to look at the tracker
themselves for an explanation
Implemented IFoo in IBar // Why it was needed?
A way to test if a commit message is written in the correct mood is to replace the blank with the message and see if
it makes sense:
This will put the currently staged changes onto the previous commit.
Note: This can also be used to edit an incorrect commit message. It will bring up the default editor (usually vi / vim
/ emacs) and allow you to change the prior message.
Amending updates the commit date but leaves the author date untouched. You can tell git to refresh the
information.
Note: Be aware that amending the most recent commit replaces it entirely and the previous commit is removed
from the branch's history. This should be kept in mind when working with public repositories and on branches with
other collaborators.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 52
This means that if the earlier commit had already been pushed, after amending it you will have to push --force.
git commit -a
If you would like to also add a commit message you would do:
You don't necessarily need to commit all files at once. Omit the -a or --all flag and specify which file you want to
commit directly:
For directly committing more than one specific file, you can specify one or multiple files, directories and patterns as
well:
git commit path/to/a/file path/to/a/folder/* path/to/b/file -m "your commit message goes here"
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 53
git add -p
or
Each of your changes will be displayed individually, and for each change you will be prompted to choose one of he
following options:
d - No, don’t add this hunk, or any other remaining hunks for this file.
Useful if you’ve already added what you want to, and want to skip over the rest.
e - Manually edit the hunk. This is probably the most powerful option.
It will open the hunk in a text editor and you can edit it as needed.
This will stage the parts of the files you choose. Then you can commit all the staged changes like this:
The changes that were not staged or committed will still appear in your working files, and can be committed later if
required. Or if the remaining changes are unwanted, they can be discarded with:
Apart from breaking up a big change into smaller commits, this approach is also useful for reviewing what you are
about to commit. By individually confirming each change, you have an opportunity to check what you wrote, and
can avoid accidentally staging unwanted code such as println/logging statements.
However, when testing build hooks, CI systems, and other systems that trigger off a commit, it's handy to be able to
easily create commits without having to edit/touch a dummy file.
You can also provide a pattern, which Git will use to search for previous authors:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 54
In this case, the author information from the most recent commit with an author containing "John" will be used.
On GitHub, commits made in either of the above ways will show a large author's thumbnail, with the committer's
smaller and in front:
/Users/davidcondrey/.gnupg/secring.gpg
--------------------------------------
sec 2048R/YOUR-16-DIGIT-KEY-ID YYYY-MM-DD [expires: YYYY-MM-DD]
3. As of version 1.7.9, git commit accepts the -S option to attach a signature to your commits. Using this option
will prompt for your GPG passphrase and will add your signature to the commit log.
git commit
The --date parameter sets the author date. This date will appear in the standard output of git log, for example.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 55
To force the commit date too:
The date parameter accepts the flexible formats as supported by GNU date, for example:
When the date doesn't specify time, the current time will be used and only the date will be overridden.
or even
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 56
Chapter 11: Aliases
Section 11.1: Simple aliases
There are two ways of creating aliases in Git:
[alias]
ci = commit
st = status
co = checkout
As with regular git commands, aliases can be used beside arguments. For example:
Searching aliases
aliases = !git config --list | grep ^alias\\. | cut -c 7- | grep -Ei --color \"$1\" "#"
[alias]
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 57
temp = !git add -A && git commit -m "Temp"
The fact that full shell syntax is available in these prefixed aliases also means you can use shell functions to
construct more complex aliases, such as ones which utilize command line arguments:
[alias]
ignore = "!f() { echo $1 >> .gitignore; }; f"
The above alias defines the f function, then runs it with any arguments you pass to the alias. So running git
ignore .tmp/ would add .tmp/ to your .gitignore file.
In fact, this pattern is so useful that Git defines $1, $2, etc. variables for you, so you don't even have to define a
special function for it. (But keep in mind that Git will also append the arguments anyway, even if you access it via
these variables, so you may want to add a dummy command at the end.)
Note that aliases prefixed with ! in this way are run from the root directory of your git checkout, even if your
current directory is deeper in the tree. This can be a useful way to run a command from the root without having to
cd there explicitly.
[alias]
ignore = "! echo $1 >> .gitignore"
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 58
cyan)<%an>%Creset'
lgb = log --graph --date-order --branches --first-parent \
--pretty=format:'%C(auto)%h%Creset %C(auto)%d%Creset %s %C(green)(%ad) %C(bold
cyan)<%an>%Creset'
lga = log --graph --date-order --all \
--pretty=format:'%C(auto)%h%Creset %C(auto)%d%Creset %s %C(green)(%ad) %C(bold
cyan)<%an>%Creset'
Here an explanation of the options and placeholder used in the --pretty format (exhaustive list are available with
git help log )
--branches - show all local branches (by default, only current branch is shown)
%s - commit message
%ad - author date (will follow --date directive) (and not commiter date)
Shows one line per file, so you can grep (only directories):
Or count:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 59
~$ git ignored | wc -l
199811 # oops, my home directory is getting crowded
[alias]
up = pull --rebase
This will update with your upstream source, then reapply any work you have not pushed on top of whatever you
pulled down.
To use:
git up
Now, any time you want to unstage stages files, type git unstage and you are good to go.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 60
Chapter 12: Rebasing
Parameter Details
--continue Restart the rebasing process after having resolved a merge conflict.
Abort the rebase operation and reset HEAD to the original branch. If branch was provided when
--abort the rebase operation was started, then HEAD will be reset to branch. Otherwise HEAD will be
reset to where it was when the rebase operation was started.
--keep-empty Keep the commits that do not change anything from its parents in the result.
--skip Restart the rebasing process by skipping the current patch.
Use merging strategies to rebase. When the recursive (default) merge strategy is used, this
allows rebase to be aware of renames on the upstream side. Note that a rebase merge works by
-m, --merge replaying each commit from the working branch on top of the upstream branch. Because of this,
when a merge conflict happens, the side reported as ours is the so-far rebased series, starting
with upstream, and theirs is the working branch. In other words, the sides are swapped.
Show a diffstat of what changed upstream since the last rebase. The diffstat is also controlled by
--stat
the configuration option rebase.stat.
-x, --exec command Perform interactive rebase, stopping between each commit and executing command
To rebase a branch, checkout the branch and then rebase it on top of another branch.
A---B---C topic
/
D---E---F---G master
To turn into:
A'--B'--C' topic
/
D---E---F---G master
These operations can be combined into a single command that checks out the branch and immediately rebases it:
git rebase master topic # rebase topic branch onto master branch
Important: After the rebase, the applied commits will have a different hash. You should not rebase commits you
have already pushed to a remote host. A consequence may be an inability to git push your local rebased branch to
a remote host, leaving your only option to git push --force.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 61
git checkout topic
git rebase master # rebase topic branch on top of master branch
The first thing a rebase does is resetting the HEAD to master; before cherry-picking commits from the old branch
topic to a new one (every commit in the former topic branch will be rewritten and will be identified by a different
hash).
With respect to terminologies used by merge tools (not to be confused with local ref or remote ref)
That means a merge/diff tool will present the upstream branch as local (master: the branch on top of which you
are rebasing), and the working branch as remote (topic: the branch being rebased)
+-----------------------------------------+
| LOCAL:master | BASE | REMOTE:topic |
+-----------------------------------------+
| MERGED |
+-----------------------------------------+
Inversion illustrated
On a merge:
We don't change the current branch topic, so what we have is still what we were working on (and we merge from
another branch)
On a rebase:
But on a rebase we switch sides because the first thing a rebase does is to checkout the upstream branch to replay
the current commits on top of it!
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 62
A git rebase upstream will first set HEAD to the upstream branch, hence the switch of 'ours' and 'theirs' compared
to the previous "current" working branch.
The rebase will then replay 'their' commits on the new 'our' topic branch:
c--c..x..x..x <- old "theirs" commits, now "ghosts", available through "reflogs"
\
\
\--y--y--y--x'--x'--x'(*) <- topic once all x's are replayed,
^ point branch topic to this commit
|
upstream branch
git rebase -i
The -i option refers to interactive mode. Using interactive rebase, the user can change commit messages, as well as
reorder, split, and/or squash (combine to one) commits.
Say you want to rearrange your last three commits. To do this you can run:
After executing the above instruction, a file will be opened in your text editor where you will be able to select how
your commits will be rebased. For the purpose of this example, just change the order of your commits, save the file,
and close the editor. This will initiate a rebase with the order you've applied. If you check git log you will see your
commits in the new order you specified.
Now, you've decided that one of the commit messages is vague and you want it to be more descriptive. Let's
examine the last three commits using the same command.
Instead of rearranging the order the commits will be rebased, this time we will change pick, the default, to reword
on a commit where you would like to change the message.
When you close the editor, the rebase will initiate and it will stop at the specific commit message that you wanted to
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 63
reword. This will let you change the commit message to whichever you desire. After you've changed the message,
simply close the editor to proceed.
Besides changing the commit message you can also adapt the changes done by the commit. To do so just change
pick to edit for one commit. Git will stop when it arrives at that commit and provide the original changes of the
commit in the staging area. You can now adapt those changes by unstaging them or adding new changes.
As soon as the staging area contains all changes you want in that commit, commit the changes. The old commit
message will be shown and can be adapted to reflect the new commit.
Say you've made a commit but decided at a later point this commit could be split into two or more commits instead.
Using the same command as before, replace pick with edit instead and hit enter.
Now, git will stop at the commit you have marked for editing and place all of its content into the staging area. From
that point you can run git reset HEAD^ to place the commit into your working directory. Then, you can add and
commit your files in a different sequence - ultimately splitting a single commit into n commits instead.
Say you have done some work and have multiple commits which you think could be a single commit instead. For
that you can carry out git rebase -i HEAD~3, replacing 3 with an appropriate amount of commits.
This time replace pick with squash instead. During the rebase, the commit which you've instructed to be squashed
will be squashed on top of the previous commit; turning them into a single commit instead.
However, Git does not allow a rebase to start if the working directory is not clean. Autostash to the rescue:
The autostash will be applied whenever the rebase is finished. It does not matter whether the rebase finishes
successfully, or if it is aborted. Either way, the autostash will be applied. If the rebase was successful, and the base
commit therefore changed, then there may be a conflict between the autostash and the new commits. In this case,
you will have to resolve the conflicts before committing. This is no different than if you would have manually
stashed, and then applied, so there is no downside to doing it automatically.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 64
Section 12.6: Testing all commits during rebase
Before making a pull request, it is useful to make sure that compile is successful and tests are passing for each
commit in the branch. We can do that automatically using -x parameter.
For example:
will perform the interactive rebase and stop after each commit to execute make. In case make fails, git will stop to
give you an opportunity to fix the issues and amend the commit before proceeding with picking the next one.
This goal is to reorganize all of your scattered commits into more meaningful commits for easier code reviews. If
there are too many layers of changes across too many files at once, it is harder to do a code review. If you can
reorganize your chronologically created commits into topical commits, then the code review process is easier (and
possibly less bugs slip through the code review process).
This overly-simplified example is not the only strategy for using git to do better code reviews. It is the way I do it,
and it's something to inspire others to consider how to make code reviews and git history easier/better.
Assuming:
Strategy:
Example:
$ git log --oneline master..
975430b db adding works: db.sql logic.rb
3702650 trying to allow adding todo items: page.html logic.rb
43b075a first draft: page.html and db.sql
$ git rebase -i master
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 65
pick 43b075a first draft: page.html and db.sql
pick 3702650 trying to allow adding todo items: page.html logic.rb
pick 975430b db adding works: db.sql logic.rb
Change it to this:
Then git will apply one commit at a time. After each commit, it will show a prompt, and then you can do the
following:
$ git status
rebase in progress; onto 4975ae9
You are currently editing a commit while rebasing branch 'feature' on '4975ae9'.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
Then you will repeat those steps for every commit. In the end, you have this:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 66
pick 3264de2 adding todo items: page.html
pick 06f81c9 db adding works: db.sql
pick 0309336 db adding works: logic.rb
Change it to this:
NOTICE: make sure that you tell git rebase to apply/squash the smaller topical commits in the order they were
chronologically commited. Otherwise you might have false, needless merge conflicts to deal with.
When that interactive rebase is all said and done, you get this:
Recap
You have now rebased your chronological commits into topical commits. In real life, you may not need to do this
every single time, but when you do want or need to do this, now you can. Plus, hopefully you learned more about
git rebase.
To do this, simply delete all commits and actions (i.e. all lines not starting with the # sign) and the rebase will be
aborted!
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 67
Section 12.9: Setup git-pull for automatically perform a
rebase instead of a merge
If your team is following a rebase-based workflow, it may be a advantageous to setup git so that each newly created
branch will perform a rebase operation, instead of a merge operation, during a git pull.
To setup every new branch to automatically rebase, add the following to your .gitconfig or .git/config:
[branch]
autosetuprebase = always
Alternatively, you can setup the git pull command to always behave as if the option --rebase was passed:
[pull]
rebase = true
This can be solved with a git push --force, but consider git push --force-with-lease, indicating that you want
the push to fail if the local remote-tracking branch differs from the branch on the remote, e.g., someone else
pushed to the remote after the last fetch. This avoids inadvertently overwriting someone else's recent push.
Note: git push --force - and even --force-with-lease for that matter - can be a dangerous command because
it rewrites the history of the branch. If another person had pulled the branch before the forced push, his/her git
pull or git fetch will have errors because the local history and the remote history are diverged. This may cause
the person to have unexpected errors. With enough looking at the reflogs the other user's work can be recovered,
but it can lead to a lot of wasted time. If you must do a forced push to a branch with other contributors, try to
coordinate with them so that they do not have to deal with errors.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 68
Chapter 13: Configuration
Parameter Details
Edits the system-wide configuration file, which is used for every user (on Linux, this file is located at
--system
$(prefix)/etc/gitconfig)
Edits the global configuration file, which is used for every repository you work on (on Linux, this file is
--global
located at ~/.gitconfig
Edits the respository-specific configuration file, which is located at .git/config in your repository; this
--local
is the default setting
Or for all commands run in a terminal. Note: This only applies until you close the terminal.
$ export GIT_EDITOR=nano
To change the editor for all terminal programs, not just Git, set the VISUAL or EDITOR environment variable.
(See VISUAL vs EDITOR.)
$ export EDITOR=nano
Note: As above, this only applies to the current terminal; your shell will usually have a configuration file to
allow you to set it permanently. (On bash, for example, add the above line to your ~/.bashrc or
~/.bash_profile.)
Some text editors (mostly GUI ones) will only run one instance at a time, and generally quit if you already have an
instance of them open. If this is the case for your text editor, Git will print the message Aborting commit due to
empty commit message. without allowing you to edit the commit message first. If this happens to you, consult your
text editor's documentation to see if it has a --wait flag (or similar) that will make it pause until the document is
closed.
This enables autocorrect in git and will forgive you for your minor mistakes (e.g. git stats instead of git status).
The parameter you supply to help.autocorrect determines how long the system should wait, in tenths of a
second, before automatically applying the autocorrected command. In the command above, 17 means that git
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 69
should wait 1.7 seconds before applying the autocorrected command.
However, bigger mistakes will be considered as missing commands, so typing something like git testingit would
result in testingit is not a git command.
If you intend the change to be true for all your repositories, use --global
Add:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 70
[includeIf "gitdir:D:/work"]
path = .gitconfig-work.config
[includeIf "gitdir:D:/opensource/"]
path = .gitconfig-opensource.config
Notes
.gitconfig-work.config
[user]
name = Money
email = [email protected]
.gitconfig-opensource.config
[user]
name = Nice
email = [email protected]
6 files:
%ALLUSERSPROFILE%\Git\Config (Windows only)
(system) <git>/etc/gitconfig, with <git> being the git installation path.
(on Windows, it is <git>\mingw64\etc\gitconfig)
(system) $XDG_CONFIG_HOME/git/config (Linux/Mac only)
(global) ~/.gitconfig (Windows: %USERPROFILE%\.gitconfig)
(local) .git/config (within a git repo $GIT_DIR)
a dedicated file (with git config -f), used for instance to modify the config of submodules: git
config -f .gitmodules ...
the command line with git -c: git -c core.autocrlf=false fetch would override any other
core.autocrlf to false, just for that fetch command.
The order is important: any config set in one source can be overridden by a source listed below it.
git config --system/global/local is the command to list 3 of those sources, but only git config -l would list all
resolved configs.
"resolved" means it lists only the final overridden config value.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 71
Since git 2.8, if you want to see which config comes from which file, you type:
When working with a team who uses different operating systems (OS) across the project, sometimes you may run
into trouble when dealing with line endings.
Microsoft Windows
When working on Microsoft Windows operating system (OS), the line endings are normally of form - carriage return
+ line feed (CR+LF). Opening a file which has been edited using Unix machine such as Linux or OSX may cause
trouble, making it seem that text has no line endings at all. This is due to the fact that Unix systems apply different
line-endings of form line feeds (LF) only.
On checkout, This instruction will ensure line-endings are configured in accordance with Microsoft Windows OS (LF
-> CR+LF)
Similarly, there might be issues when the user on Unix based OS tries to read files which have been edited on
Microsoft Windows OS. In order to prevent any unexpected issues run
Note: for that example you don't need to precise both user.name and user.email, git will complete the missing
information from the previous commits.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 72
git config --global --unset http.proxy
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 73
Chapter 14: Branching
Parameter Details
Delete a branch. The branch must be fully merged in its upstream branch, or in HEAD if no upstream
-d, --delete
was set with --track or --set-upstream
-D Shortcut for --delete --force
-m, --move Move/rename a branch and the corresponding reflog
-M Shortcut for --move --force
-r, --remotes List or delete (if used with -d) the remote-tracking branches
-a, --all List both remote-tracking branches and local branches
Activate the list mode. git branch <pattern> would try to create a branch, use git branch --
--list
list <pattern> to list matching branches
If specified branch does not exist yet or if --force has been given, acts exactly like --track.
--set-upstream Otherwise sets up configuration like --track would when creating the branch, except that where
branch points to is not changed
Generally, the branch name must not contain spaces and is subject to other specifications listed here. To switch to
an existing branch :
To create a branch at a point other than the last commit of the current branch (also known as HEAD), use either of
these commands:
The <start-point> can be any revision known to git (e.g. another branch name, commit SHA, or a symbolic
reference such as HEAD or a tag name):
If a given branch name is only found on one remote, you can simply use
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 74
git checkout -b <branch_name>
which is equivalent to
Sometimes you may need to move several of your recent commits to a new branch. This can be achieved by
branching and "rolling back", like so:
Initial state After git branch <new_name> After git reset --hard HEAD~2
newBranch newBranch
↓ ↓
A-B-C-D-E (HEAD) A-B-C-D-E (HEAD) A-B-C-D-E (HEAD)
↑ ↑ ↑
master master master
Goal Command
List local branches git branch
List local branches verbose git branch -v
List remote and local branches git branch -a OR git branch --all
List remote and local branches (verbose) git branch -av
List remote branches git branch -r
List remote branches with latest commit git branch -rv
List merged branches git branch --merged
List unmerged branches git branch --no-merged
List branches containing commit git branch --contains [<commit>]
Notes:
Adding an additional v to -v e.g. $ git branch -avv or $ git branch -vv will print the name of the
upstream branch as well.
Branches shown in red color are remote branches
and as of Git version 1.7.0, you can delete a remote branch using
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 75
git push origin --delete <branchName>
To delete a branch locally. Note that this will not delete the branch if it has any unmerged changes:
git checkout -
where:
Deletes the branch named dev if its changes are merged with another branch and will not be lost. If the dev branch
does contain changes that have not yet been merged that would be lost, git branch -d will fail:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 76
$ git branch -d dev
error: The branch 'dev' is not fully merged.
If you are sure you want to delete it, run 'git branch -D dev'.
Per the warning message, you can force delete the branch (and lose any unmerged changes in that branch) by
using the -D flag:
The first commit made on this new branch will have no parents and it will be the root of a new history
totally disconnected from all the other branches and commits.
source
To list local and remote branches that contain a specific commit or tag
For example:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 77
As an example, you usually run git push origin master to push your local changes to your online repository.
Using -u (short for --set-upstream) will set up the tracking information during the push.
By default, git pushes the local branch to a remote branch with the same name. For example, if you have a local
called new-feature, if you push the local branch it will create a remote branch new-feature as well. If you want to
use a different name for the remote branch, append the remote name after the local branch name, separated by ::
Please note that this will overwrite your branch's current commit, and as so, its entire history. You might loose
some work by issuing this command. If that's the case, you can use the reflog to recover the lost commits. It can be
advised to perform this command on a new branch instead of your current one.
However, this command can be particularly useful when rebasing or doing such other large history modifications.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 78
Chapter 15: Rev-List
Parameter Details
--oneline Display commits as a single line with their title.
Git rev-list will list commits in one branch that are not in another branch. It is a great tool when you're trying to
figure out if code has been merged into a branch or not.
Using the --oneline option will display the title of each commit.
The ^ operator excludes commits in the specified branch from the list.
You can pass more than two branches if you want. For example, git rev-list foo bar ^baz lists commits
in foo and bar, but not baz.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 79
Chapter 16: Squashing
Section 16.1: Squash Recent Commits Without Rebasing
If you want to squash the previous x commits into a single one, you can use the following commands:
Replacing x with the number of previous commits you want to be included in the squashed commit.
Mind that this will create a new commit, essentially forgetting information about the previous x commits including
their author, message and date. You probably want to first copy-paste an existing commit message.
This is more or less equivalent to using git reset, but is more convenient when changes being incorporated have a
symbolic name. Compare:
1. Determine which commit you would like to rebase from, and note its commit hash.
Alternatively, you can type HEAD~4 instead of a commit hash, to view the latest commit and 4 more commits
before the latest one.
3. In the editor that opens when running this command, determine which commits you want to squash.
Replace pick at the beginning of those lines with squash to squash them into the previous commit.
4. After selecting which commits you would like to squash, you will be prompted to write a commit message.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 80
17692d1 Did some more stuff
e647334 Another Commit
2e30df6 Initial commit
At this point your editor of choice pops up where you can describe what you want to do with the commits. Git
provides help in the comments. If you leave it as is then nothing will happen because every commit will be kept and
their order will be the same as they were before the rebase. In this example we apply the following commands:
git commit --squash=[commit hash of commit to which this commit will be squashed to]
It is also possible to use words from the commit message instead of the commit hash, like so,
where the most recent commit with the word 'things' would be used.
These commits' message would begin with 'fixup!' or 'squash!' followed by the rest of the commit message to
which these commits will be squashed to.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 81
When rebasing --autosquash flag should be used to use the autosquash/fixup feature.
Once you've made your changes, you can add them to the index as usual, then commit them using the --fixup
argument with a reference to the commit you want to squash into:
$ git add .
$ git commit --fixup bbb2222
[my-feature-branch ddd4444] fixup! A second commit
This will create a new commit with a commit message that Git can recognize during an interactive rebase:
Git will propose you to squash the commit you made with the commit --fixup into the correct position:
To avoid having to type --autosquash on every rebase, you can enable this option by default:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 82
Chapter 17: Cherry Picking
Parameters Details
-e, --edit With this option, git cherry-pick will let you edit the commit message prior to committing.
When recording the commit, append a line that says "(cherry picked from commit …)" to the original
-x commit message in order to indicate which commit this change was cherry-picked from. This is done
only for cherry picks without conflicts.
If the current HEAD is the same as the parent of the cherry-pick’ed commit, then a fast forward to this
--ff
commit will be performed.
Continue the operation in progress using the information in .git/sequencer. Can be used to continue
--continue
after resolving conflicts in a failed cherry-pick or revert.
Forget about the current operation in progress. Can be used to clear the sequencer state after a failed
--quit
cherry-pick or revert.
--abort Cancel the operation and return to the pre-sequence state.
A cherry-pick takes the patch that was introduced in a commit and tries to reapply it on the branch you’re currently
on.
We can run
Where the new commit a66b23 has the same content (source diff, commit message) as b886a0 (but a different
parent). Note that cherry-picking will only pick up changes on that commit(b886a0 in this case) not all the changes in
feature branch (for this you will have to either use rebasing or merging).
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 83
git cherry-pick <commit-A>^..<commit-B> will place commit A and every commit up to and including B on top of
the currently checked-out branch.
git branch --contains <commit> lists local branches that contain the specified commit.
git branch -r --contains <commit> also includes remote tracking branches in the list.
Example:
+ 492508acab7b454eee8b805f8ba906056eede0ff
- 5ceb5a9077ddb9e78b1e8f24bfc70e674c627949
+ b4459544c000f4d51d1ec23f279d9cdb19c1d32b
+ b6ce3b78e938644a293b2dd2a15b2fecb1b54cd9
The commits that being with + will be the ones that haven't yet cherry-picked into development.
Syntax:
Options:
< upstream > Upstream branch to search for equivalent commits. Defaults to the upstream branch of HEAD.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 84
Chapter 18: Recovering
Section 18.1: Recovering from a reset
With Git, you can (almost) always turn the clock back
Don't be afraid to experiment with commands that rewrite history*. Git doesn't delete your commits for 90 days by
default, and during that time you can easily recover them from the reflog:
* Watch out for options like --hard and --force though — they can discard data.
* Also, avoid rewriting history on any branches you're collaborating on.
Choose a different git stash to restore with the number that shows up for the stash you want
You can also choose 'git stash pop', it works same as 'git stash apply' like..
or
git stash pop: stash data will be remove from stack of stash list.
Ex:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 85
git stash list
stash@{0}: WIP on master: 70f0d95 Add user role to localStorage on user login
You can see one stash data is removed (popped) from stash list and stash@{1} became stash@{0}.
git reflog
First find the commit id of the commit that deleted your file.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 86
If you have already made local changes to the file (that you do not require!) you can also use the --hard option
git reflog
You will not be able to recover deleted branches if git's garbage collector deleted dangling commits - those without
refs. Always have a backup of your repository, especially when you work in a small team / proprietary project
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 87
Chapter 19: Git Clean
Parameter Details
Remove untracked directories in addition to untracked files. If an untracked directory is managed by
-d a different Git repository, it is not removed by default. Use -f option twice if you really want to
remove such a directory.
If the Git configuration variable clean. requireForce is not set to false, git clean will refuse to delete
-f, --force files or directories unless given -f, -n or -i. Git will refuse to delete directories with .git sub directory
or file unless a second -f is given.
-i, --interactive Interactively prompts the removal of each file.
-n, --dry-run Only displays a list of files to be removed, without actually removing them.
-q,--quiet Only display errors, not the list of successfully removed files.
Will print out items to be removed and ask for a confirmation via commands like the follow:
Interactive option i can be added along with other options like X, d, etc.
Will remove all ignored files from the current directory and all subdirectories.
Will remove all untracked directories and the files within them. It will start at the current working directory and will
iterate through all subdirectories.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 88
git clean -dn
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 89
Chapter 20: Using a .gitattributes file
Section 20.1: Automatic Line Ending Normalization
Create a .gitattributes file in the project root containing:
* text=auto
This will result in all text files (as identified by Git) being committed with LF, but checked out according to the host
operating system default.
input on Linux/macOS
true on Windows
*.png binary
https://gitattributes.io/
https://github.com/alexkaratarakis/gitattributes
* -text
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 90
Chapter 21: .mailmap file: Associating
contributor and email aliases
Section 21.1: Merge contributers by aliases to show commit
count in shortlog
When contributors add to a project from different machines or operating systems, it may happen that they use
different email addresses or names for this, which will fragment contributor lists and statistics.
Running git shortlog -sn to get a list of contributors and the number of commits by them could result in the
following output:
This fragmentation/disassociation may be adjusted by providing a plain text file .mailmap, containing email
mappings.
All names and email addresses listed in one line will be associated to the first named entity respectively.
Once this file exists in the project's root, running git shortlog -sn again will result in a condensed list:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 91
Chapter 22: Analyzing types of workflows
Section 22.1: Centralized Workflow
With this fundamental workflow model, a master branch contains all active development. Contributors will need to
be especially sure they pull the latest changes before continuing development, for this branch will be changing
rapidly. Everyone has access to this repo and can commit changes right to the master branch.
This is the classic version control paradigm, upon which older systems like Subversion and CVS were built.
Softwares that work this way are called Centralized Version Control Systems, or CVCS's. While Git is capable of
working this way, there are notable disadvantages, such as being required to precede every pull with a merge. It's
very possible for a team to work this way, but the constant merge conflict resolution can end up eating a lot of
valuable time.
This is why Linus Torvalds created Git not as a CVCS, but rather as a DVCS, or Distributed Version Control System,
similar to Mercurial. The advantage to this new way of doing things is the flexibility demonstrated in the other
examples on this page.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 92
Section 22.2: Gitflow Workflow
Originally proposed by Vincent Driessen, Gitflow is a development workflow using git and several pre-defined
branches. This can seen as a special case of the Feature Branch Workflow.
The idea of this one is to have separate branches reserved for specific parts in development:
master branch is always the most recent production code. Experimental code does not belong here.
develop branch contains all of the latest development. These developmental changes can be pretty much
anything, but larger features are reserved for their own branches. Code here is always worked on and
merged into release before release / deployment.
hotfix branches are for minor bug fixes, which cannot wait until the next release. hotfix branches come off
of master and are merged back into both master and develop.
release branches are used to release new development from develop to master. Any last minute changes,
such as bumping version numbers, are done in the release branch, and then are merged back into master
and develop. When deploying a new version, master should be tagged with the current version number (e.g.
using semantic versioning) for future reference and easy rollback.
feature branches are reserved for bigger features. These are specifically developed in designated branches
and integrated with develop when finished. Dedicated feature branches help to separate development and
to be able to deploy done features independently from each other.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 93
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 94
Section 22.3: Feature Branch Workflow
The core idea behind the Feature Branch Workflow is that all feature development should take place in a dedicated
branch instead of the master branch. This encapsulation makes it easy for multiple developers to work on a
particular feature without disturbing the main codebase. It also means the master branch will never contain broken
code, which is a huge advantage for continuous integration environments.
Encapsulating feature development also makes it possible to leverage pull requests, which are a way to initiate
discussions around a branch. They give other developers the opportunity to sign off on a feature before it gets
integrated into the official project. Or, if you get stuck in the middle of a feature, you can open a pull request asking
for suggestions from your colleagues. The point is, pull requests make it incredibly easy for your team to comment
on each other’s work.
Master branch of a specific location (Github, Gitlab, Bitbucket, local server) contains the latest shippable version.
For each new feature/bug fix/architectural change each developer creates a branch.
Changes happen on that branch and can be discussed in a pull request, code review, etc. Once accepted they get
merged to the master branch.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 95
Section 22.5: Forking Workflow
This type of workflow is fundamentally different than the other ones mentioned on this topic. Instead of having one
centralized repo that all developers have access to, each developer has his/her own repo that is forked from the
main repo. The advantage of this is that developers can post to their own repos rather than a shared repo and a
maintainer can integrate the changes from the forked repos into the original whenever appropriate.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 96
Chapter 23: Pulling
Parameters Details
--quiet No text output
-q shorthand for --quiet
verbose text output. Passed to fetch and merge/rebase
--verbose
commands respectively.
-v shorthand for --verbose
Fetch new commits for submodules? (Not that this is not a
--[no-]recurse-submodules[=yes|on-demand|no]
pull/checkout)
Unlike pushing with Git where your local changes are sent to the central repository's server, pulling with Git takes
the current code on the server and 'pulls' it down from the repository's server to your local machine. This topic
explains the process of pulling code from a repository using Git as well as the situations one might encounter while
pulling different code into the local copy.
When you are working on a remote repository (say, GitHub) with someone else, you will at some point want to
share your changes with them. Once they have pushed their changes to a remote repository, you can retrieve those
changes by pulling from this repository.
git pull
You can pull changes from a different remote or branch by specifying their names
Will pull the branch feature-A form origin into your local branch. Note that you can directly supply an URL instead
of a remote name, and an object name such as a commit SHA instead of a branch name.
Manual pull
To imitate the behavior of a git pull, you can use git fetch then git merge
git fetch origin # retrieve objects and update refs from origin
git merge origin/feature-A # actually perform the merge
This can give you more control, and allows you to inspect the remote branch before merging it. Indeed, after
fetching, you can see the remote branches with git branch -a, and check them out with
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 97
git merge local-branch-name # performing the merge
error: Your local changes to the following files would be overwritten by merge
In order to update (like svn update did with subversion), you can run :
git stash
git pull --rebase
git stash pop
git up
Beware: While commits discarded using reset --hard can be recovered using reflog and reset, uncommitted
changes are deleted forever.
Change origin and master to the remote and branch you want to forcibly pull to, respectively, if they are named
differently.
If you are pulling in fresh commits from the remote repository and you have local changes on the current branch
then git will automatically merge the remote version and your version. If you would like to reduce the number of
merges on your branch you can tell git to rebase your commits on the remote version of the branch.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 98
Making it the default behavior
To make this the default behavior for newly created branches, type the following command:
And
Check if fast-forwardable
To only allow fast forwarding the local branch, you can use:
This will display an error when the local branch is not fast-forwardable, and needs to be either rebased or merged
with upstream.
To fix the problem:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 99
Chapter 24: Hooks
Section 24.1: Pre-push
Available in Git 1.8.2 and above.
Version ≥ 1.8
Pre-push hooks can be used to prevent a push from going though. Reasons this is helpful include: blocking
accidental manual pushes to specific branches, or blocking pushes if an established check fails (unit tests, syntax).
A pre-push hook is created by simply creating a file named pre-push under .git/hooks/, and (gotcha alert),
making sure the file is executable: chmod +x ./git/hooks/pre-push.
#!/bin/bash
protected_branch='master'
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
if [ $protected_branch = $current_branch ]
then
read -p "You're about to push master, is that what you intended? [y|n] " -n 1 -r < /dev/tty
echo
if echo $REPLY | grep -E '^[Yy]$' > /dev/null
then
exit 0 # push will execute
fi
exit 1 # push will not execute
else
exit 0 # push will execute
fi
Here's an example from Volkan Unsal which makes sure RSpec tests pass before allowing the push:
#!/usr/bin/env ruby
require 'pty'
html_path = "rspec_results.html"
begin
PTY.spawn( "rspec spec --format h > rspec_results.html" ) do |stdin, stdout, pid|
begin
stdin.each { |line| print line }
rescue Errno::EIO
end
end
rescue PTY::ChildExited
puts "Child process exit!"
end
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 100
if errors.zero?
puts "0 failed! #{examples} run, #{pending} pending"
# HTML Output when tests ran successfully:
# puts "View spec results at #{File.expand_path(html_path)}"
sleep 1
exit 0
else
puts "\aCOMMIT FAILED!!"
puts "View your rspec results at #{File.expand_path(html_path)}"
puts
puts "#{errors} failed! #{examples} run, #{pending} pending"
# Open HTML Ooutput when tests failed
# `open #{html_path}`
exit 1
end
As you can see, there are lots of possibilities, but the core piece is to exit 0 if good things happened, and exit 1 if
bad things happened. Anytime you exit 1 the push will be prevented and your code will be in the state it was
before running git push....
When using client side hooks, keep in mind that users can skip all client side hooks by using the option "--no-verify"
on a push. If you're relying on the hook to enforce process, you can get burned.
Documentation: https://git-scm.com/docs/githooks#_pre_push
Official Sample:
https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-push.sample
#!/bin/sh
if [ -s pom.xml ]; then
echo "Running mvn verify"
mvn clean verify
if [ $? -ne 0 ]; then
echo "Maven build failed"
exit 1
fi
fi
$ cat .git/hooks/post-receive
#!/bin/bash
IFS=' '
while read local_ref local_sha remote_ref remote_sha
do
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 101
echo Forwarding feature branch to other repository: $ref
git push -q --force other_repos $ref
}
done
In this example, the egrep regexp looks for a specific branch format (here: JIRA-12345 as used to name Jira issues).
You can leave this part off if you want to forward all branches, of course.
The only argument passed to this hook is the name of the file that contains the message. If you don't like the
message that the user has entered, you can either alter this file in-place (same as prepare-commit-msg) or you can
abort the commit entirely by exiting with a non-zero status.
The following example is used to check if the word ticket followed by a number is present on the commit message
word="ticket [0-9]"
isPresent=$(grep -Eoh "$word" $1)
if [[ -z $isPresent ]]
then echo "Commit message KO, $word is missing"; exit 1;
else echo "Commit message OK"; exit 0;
fi
There are six types of local hooks: pre-commit, prepare-commit-msg, commit-msg, post-commit, post-checkout,
and pre-rebase.
The first four hooks relate to commits and allow you to have some control over each part in a commit's life cycle.
The final two let you perform some extra actions or safety checks for the git checkout and git rebase commands.
All of the "pre-" hooks let you alter the action that’s about to take place, while the "post-" hooks are used primarily
for notifications.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 102
Its exit status has no affect on the git checkout command.
The script takes no parameters, and its exit status does not affect the commit in any way.
The script takes no parameters, but is sent the same information as pre-receive via standard input:
This type of hook is useful for running automated tests to make sure the incoming commit doesn't break existing
functionality of your project. This type of hook may also check for whitespace or EOL errors.
No arguments are passed to the pre-commit script, and exiting with a non-zero status aborts the entire commit.
1. the upstream branch that the series was forked from, and
2. the branch being rebased (empty when rebasing the current branch).
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 103
You can abort the rebase operation by exiting with a non-zero status.
The hook runs before any references are updated. It is typically used to enforce any kind of development policy.
The script takes no parameters, but each ref that is being pushed is passed to the script on a separate line on
standard input in the following format:
This is the same information passed to pre-receive, but since update is invoked separately for each ref, you can
reject some refs while allowing others.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 104
Chapter 25: Cloning Repositories
Section 25.1: Shallow Clone
Cloning a huge repository (like a project with multiple years of history) might take a long time, or fail because of the
amount of data to be transferred. In cases where you don't need to have the full history available, you can do a
shallow clone:
The above command will fetch just the last commit from the remote repository.
Be aware that you may not be able to resolve merges in a shallow repository. It's often a good idea to take at least
as many commits are you are going to need to backtrack to resolve merges. For example, to instead get the last 50
commits:
Later, if required, you can the fetch the rest of the repository:
Version ≥ 1.8.3
The example above will place it in a directory with the same name as the repository name.
To use the shorthand option for --branch, type -b. This command downloads entire repository and checks out
<branch name>.
To save disk space you can clone history leading only to single branch with:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 105
If --single-branch is not added to the command, history of all branches will be cloned into [directory]. This can
be issue with big repositories.
To later undo --single-branch flag and fetch the rest of repository use command:
Clones the repository and also clones all submodules. If the submodules themselves contain additional
submodules, Git will also clone those.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 106
Chapter 26: Stashing
Parameter Details
Show the changes recorded in the stash as a diff between the stashed state and its original parent.
show
When no <stash> is given, shows the latest one.
List the stashes that you currently have. Each stash is listed with its name (e.g. stash@{0} is the latest
list stash, stash@{1} is the one before, etc.), the name of the branch that was current when the stash was
made, and a short description of the commit the stash was based on.
pop Remove a single stashed state from the stash list and apply it on top of the current working tree state.
apply Like pop, but do not remove the state from the stash list.
Remove all the stashed states. Note that those states will then be subject to pruning, and may be
clear
impossible to recover.
Remove a single stashed state from the stash list. When no <stash> is given, it removes the latest one.
drop
i.e. stash@{0}, otherwise <stash> must be a valid stash log reference of the form stash@{<revision>}.
Create a stash (which is a regular commit object) and return its object name, without storing it
create anywhere in the ref namespace. This is intended to be useful for scripts. It is probably not the
command you want to use; see "save" above.
Store a given stash created via git stash create (which is a dangling merge commit) in the stash ref,
store updating the stash reflog. This is intended to be useful for scripts. It is probably not the command you
want to use; see "save" above.
modified: business/com/test/core/actions/Photo.c
no changes added to commit (use "git add" and/or "git commit -a")
If you have added files to your working directory these can be stashed as well. You just need to stage them first.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 107
NewPhoto.c
nothing added to commit but untracked files present (use "git add" to track)
(master) $ git stage NewPhoto.c
(master) $ git stash
Saved working directory and index state WIP on master:
(master) $ git status
On branch master
nothing to commit, working tree clean
(master) $
Your working directory is now clean of any changes you made. You can see this by re-running git status:
To apply the very last stash, run git stash apply (additionally, you can apply and remove the last stashed changed
with git stash pop):
modified: business/com/test/core/actions/Photo.c
no changes added to commit (use "git add" and/or "git commit -a")
Note, however, that stashing does not remember the branch you were working on. In the above examples, the user
was stashing on master. If they switch to the dev branch, dev, and run git stash apply the last stash is put on
the dev branch.
modified: business/com/test/core/actions/Photo.c
no changes added to commit (use "git add" and/or "git commit -a")
git stash
To include all untracked files in the stash use the --include-untracked or -u flags.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 108
To include a message with your stash to make it more easily identifiable later
To leave the staging area in current state after stash use the --keep-index or -k flags.
Or a specific stash
Or a specific stash
git stash -p
As of version 2.13.0 you can also avoid the interactive mode and create a partial stash with a pathspec using the
new push keyword.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 109
git stash push -m "My partial stash" -- app.config
This will list all stashes in the stack in reverse chronological order.
You will get a list that looks something like this:
You can refer to specific stash by its name, for example stash@{1}.
git stash
git checkout correct-branch
git stash pop
Remember git stash pop will apply the last stash and delete it from the stash list. To keep the stash in the list and
only apply to some branch you can use:
Or a specific stash
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 110
git stash apply
Choose a different git stash to restore with the number that shows up for the stash you want
Suppose you don't want to stash the staged files and only stash the modified files so you can use:
Stash never saves the untracked files it only stashes the modified and staged files. So suppose if you need to stash
the untracked files too then you can use this:
git stash -u
Suppose you need to stash only some part of code from the file or only some files only from all the modified and
stashed files then you can do it like this:
Git will not stash everything that is modified but will instead prompt you interactively which of the changes you
would like to stash and which you would like to keep in your working directory.
(Note that git stash drop also produces the same line.)
This will show you all the commits at the tips of your commit graph which are no longer referenced from any
branch or tag – every lost commit, including every stash commit you’ve ever created, will be somewhere in that
graph.
The easiest way to find the stash commit you want is probably to pass that list to gitk:
gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
This will launch a repository browser showing you every single commit in the repository ever, regardless of whether it
is reachable or not.
You can replace gitk there with something like git log --graph --oneline --decorate if you prefer a nice graph
on the console over a separate GUI app.
Once you know the hash of the commit you want, you can apply it as a stash:
Or you can use the context menu in gitk to create branches for any unreachable commits you are interested in.
After that, you can do whatever you want with them with all the normal tools. When you’re done, just blow those
branches away again.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 112
Chapter 27: Subtrees
Section 27.1: Create, Pull, and Backport Subtree
Create Subtree
Then Create a subtree specifying the new folder prefix plugins/demo. plugin is the remote name, and master
refers to the master branch on the subtree's repository:
3. Cherry-pick backports:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 113
Chapter 28: Renaming
Parameter Details
-f or --force Force renaming or moving of a file even if the target exists
then rename the local branch, delete the old remote and set the new renamed branch as upstream:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 114
Chapter 29: Pushing
Parameter Details
Overwrites the remote ref to match your local ref. Can cause the remote repository to lose commits, so
--force
use with care.
--verbose Run verbosely.
<remote> The remote repository that is destination of the push operation.
<refspec>... Specify what remote ref to update with what local ref or object.
After changing, staging, and committing code with Git, pushing is required to make your changes available to others
and transfers your local changes to the repository server. This topic will cover how to properly push code using Git.
Example
git push origin master:wip-yourname
Will push your master branch to the wip-yourname branch of origin (most of the time, the repository you cloned
from).
Deleting the remote branch is the equivalent of pushing an empty object to it.
Example
git push origin :wip-yourname
Instead of using the colon, you can also use the --delete flag, which is better readable in some cases.
Example
git push origin --delete wip-yourname
If you have a single commit in your branch that you want to push to a remote without pushing anything else, you
can use the following
Example
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 115
eeb32bc Commit 1 - already pushed
347d700 Commit 2 - want to push
e539af8 Commit 3 - only local
5d339db Commit 4 - only local
to push only commit 347d700 to remote master use the following command
will push your code to your existing upstream. Depending on the push configuration, it will either push code from
you current branch (default in Git 2.x) or from all branches (default in Git 1.x).
When working with git, it can be handy to have multiple remote repositories. To specify a remote repository to push
to, just append its name to the command.
Specify Branch
Unless the branch you are working on originally comes from a remote repository, simply using git push won't work
the first time. You must perform the following command to tell git to push the current branch to a specific
remote/branch combination
Here, master is the branch name on the remote origin. You can use -u as a shorthand for --set-upstream.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 116
For more information view Adding a remote repository
Explanation
Push code means that git will analyze the differences of your local commits and remote and send them to be
written on the upstream. When push succeeds, your local repository and remote repository are synchronized and
other users can see your commits.
For more details on the concepts of "upstream" and "downstream", see Remarks.
git push -f
or
Important notes
This will overwrite any remote changes and your remote will match your local.
Attention: Using this command may cause the remote repository to lose commits. Moreover, it is strongly advised
against doing a force push if you are sharing this remote repository with others, since their history will retain every
overwritten commit, thus rending their work out of sync with the remote repository.
Nobody except you pulled the changes you are trying to overwrite
You can force everyone to clone a fresh copy after the forced push and make everyone apply their changes
to it (people may hate you for this).
Pushes all of the git tags in the local repository that are not in the remote one.
Simple pushes to the upstream branch, but will not work if the upstream branch is called something else.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 117
Upstream pushes to the upstream branch, no matter what it is called.
Matching pushes all branches that match on the local and the remote git config push.default upstream
git push
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 118
Chapter 30: Internals
Section 30.1: Repo
A git repository is an on-disk data structure which stores metadata for a set of files and directories.
It lives in your project's .git/ folder. Every time you commit data to git, it gets stored here. Inversely, .git/
contains every single commit.
.git/
objects/
refs/
blob
tree
commit
tag
You can see where it's currently pointing by checking the .git/HEAD file.
$cat .git/HEAD
ref: refs/heads/mainline
$ cat .git/HEAD
4bb6f98a223abc9345a0cef9200562333
This is what's known as a "detached head" - because HEAD is not attached to (pointing at) any ref, but rather points
directly to an object.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 119
"master" --> 1a410e...
$ cat .git/refs/heads/mainline
4bb6f98a223abc9345a0cef9200562333
This is commonly what are called branches. However, you'll note that in git there is no such thing as a branch -
only a ref.
Now, it's possible to navigate git purely by jumping around to different objects directly by their hashes. But this
would be terribly inconvenient. A ref gives you a convenient name to refer to objects by. It's much easier to ask
git to go to a specific place by name rather than by hash.
However, the commit does not directly contain any changed files or data. Rather, it contains mostly metadata and
pointers to other objects which contain the actual contents of the commit.
hash of a tree
hash of a parent commit
author name/email, commiter name/email
commit message
First commit!
Tree
A very important note is that the tree objects stores EVERY file in your project, and it stores whole files not diffs.
This means that each commit contains a snapshot of the entire project*.
*Technically, only changed files are stored. But this is more an implementation detail for efficiency. From a design
perspective, a commit should be considered as containing a complete copy of the project.
Parent
The parent line contains a hash of another commit object, and can be thought of as a "parent pointer" that points to
the "previous commit". This implicitly forms a graph of commits known as the commit graph. Specifically, it's a
directed acyclic graph (or DAG).
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 120
Section 30.6: Tree Object
A tree basically represents a folder in a traditional filesystem: nested containers for files or other folders.
A tree contains:
Just as you can use ls or dir to list the contents of a folder, you can list the contents of a tree object.
You can look up the files in a commit by first finding the hash of the tree in the commit, and then looking at that
tree:
If you have the hash of a blob, you can look at it's contents.
class Foo {
...
}
...
For example, you can browse a tree as above, and then look at one of the blobs in it.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 121
...
1. Create blobs and trees to represent your project directory - stored in .git/objects
2. Creates a new commit object with your author information, commit message, and the root tree from step 1 -
also stored in .git/objects
3. Updates the HEAD ref in .git/HEAD to the hash of the newly-created commit
This results in a new snapshot of your project being added to git that is connected to the previous state.
1. Update the files in the working directory to match the tree inside the commit
2. Update HEAD to point to the specified hash or ref
$ cat .git/head
1f324a
$ cat .git/refs/heads/TestBranch
1f324a
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 122
Chapter 31: git-tfs
Section 31.1: git-tfs clone
This will create a folder with the same name as the project, i.e. /My.Project.Name
Git can be installed first so you can state any parameters you wish. Here all the Unix tools are also installed and
'NoAutoCrlf' means checkout as is, commit as is.
This is all you really need to be able to install git-tfs via chocolatey.
This will take all of your local commits and create a single check-in.
Note: this will fail if Check-in Notes are required. These can be bypassed by adding git-tfs-force: rcheckin to
the commit message.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 123
Chapter 32: Empty directories in Git
Section 32.1: Git doesn't track directories
Assume you've initialized a project with the following directory structure:
/build
app.js
git init
git add .
git commit -m "Initial commit"
Assume you added a build step to your application and rely on the "build" directory to be there as the output
directory (and you don't want to make it a setup instruction every developer has to follow), a convention is to
include a ".gitkeep" file inside the directory and let Git track that file.
/build
.gitkeep
app.js
Git will now track the file build/.gitkeep file and therefore the build folder will be made available on checkout.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 124
Chapter 33: git-svn
Section 33.1: Cloning the SVN repository
You need to create a new local copy of the repository with the command
If your SVN repository follows the standard layout (trunk, branches, tags folders) you can save some typing:
git svn clone checks out each SVN revision, one by one, and makes a git commit in your local repository in order
to recreate the history. If the SVN repository has a lot of commits this will take a while.
When the command is finished you will have a full fledged git repository with a local branch called master that
tracks the trunk branch in the SVN repository.
will create a SVN revision for each of your local git commits. As with SVN, your local git history must be in sync with
the latest changes in the SVN repository, so if the command fails, try performing a git svn rebase first.
As the git-svn documentation states "Subversion is a system that is far less sophisticated than Git" so you can't use
all the full power of git without messing up the history in the Subversion server. Fortunately the rules are very
simple: Keep the history linear
This means you can make almost any git operation: creating branches, removing/reordering/squashing commits,
move the history around, delete commits, etc. Anything but merges. If you need to reintegrate the history of local
branches use git rebase instead.
When you perform a merge, a merge commit is created. The particular thing about merge commits is that they
have two parents, and that makes the history non-linear. Non-linear history will confuse SVN in the case you "push"
a merge commit to the repository.
However do not worry: you won't break anything if you "push" a git merge commit to SVN. If you do so, when
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 125
the git merge commit is sent to the svn server it will contain all the changes of all commits for that merge, so you
will lose the history of those commits, but not the changes in your code.
This retrieves all the changes from the SVN repository and applies them on top of your local commits in your
current branch.
to retrieve the changes from the SVN repository and bring them to your local machine but without applying them to
your local branch.
Using the --rmdir flag when issuing a comment corrects this issue, and removes an empty folder in SVN if you
locally delete the last file inside it:
Unfortunately it does not removes existing empty folders: you need to do it manually.
To avoid adding the flag each time you do a dcommit, or to play it safe if you are using a git GUI tool (like
SourceTree) you can set this behaviour as default with the command:
[svn]
rmdir = true
To remove all untracked files and folders that should be kept empty for SVN use the git command:
Please note: the previous command will remove all untracked files and empty folders, even the ones that should be
tracked by SVN! If you need to generate againg the empty folders tracked by SVN use the command
In practices this means that if you want to cleanup your workspace from untracked files and folders you should
always use both commands to recreate the empty folders tracked by SVN:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 126
Chapter 34: Archive
Parameter Details
Format of the resulting archive: tar or zip. If this options is not given and the output
--format=<fmt> file is specified, the format is inferred from the filename if possible. Otherwise,
defaults to tar.
-l, --list Show all available formats.
-v, --verbose Report progress to stderr.
--prefix=<prefix>/ Prepend <prefix>/ to each filename in the archive.
-o <file>, --output=<file> Write the archive to <file> instead of stdout.
--worktree-attributes Look for attributes in .gitattributes files in the working tree.
This can be any options that the archiver backend understands. For zip backend,
<extra> using -0 will store the files without deflating them, while -1 through -9 can be used to
adjust compression speed and ratio.
Retrieve a tar archive from a remote repository <repo> rather than the local
--remote=<repo>
repository.
--exec=<git-upload-archive> Used with --remote to specify the path to the <git-upload-archive on the remote.
<tree-ish> The tree or commit to produce an archive for.
Without an optional parameter, all files and directories in the current working
<path> directory are included in the archive. If one or more paths are specified, only these are
included.
This can also be done with (which will use the in-built tar.gz handling):
Alternatively it is possible to just specify an output file with valid extension and the format and compression type
will be inferred from it:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 127
directory. To create an archive of HEAD with a directory prefix:
When extracted all the files will be extracted inside a directory named src-directory-name in the current directory.
Create an archive of files inside a specific sub directory (sub-dir) of revision HEAD:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 128
Chapter 35: Rewriting history with filter-
branch
Section 35.1: Changing the author of commits
You can use an environment filter to change the author of commits. Just modify and export $GIT_AUTHOR_NAME in
the script to change who authored the commit.
chmod +x ./filter.sh
git filter-branch --env-filter ./filter.sh
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 129
Chapter 36: Migrating to Git
Section 36.1: SubGit
SubGit may be used to perform a one-time import of an SVN repository to git.
Use the command java -jar svn-migration-scripts.jar verify to check if your machine is missing any of the
programs necessary to complete the conversion. Specifically, this command checks for the Git, subversion, and
git-svn utilities. It also verifies that you are performing the migration on a case-sensitive file system. Migration to
Git should be done on a case-sensitive file system to avoid corrupting the repository.
Next, you need to generate an authors file. Subversion tracks changes by the committer's username only. Git,
however, uses two pieces of information to distinguish a user: a real name and an email address. The following
command will generate a text file mapping the subversion usernames to their Git equivalents:
where <svn-repo> is the URL of the subversion repository you wish to convert. After running this command, the
contributors' identification information will be mapped in authors.txt. The email addresses will be of the form
<username>@mycompany.com. In the authors file, you will need to manually change each person's default name
(which by default has become their username) to their actual names. Make sure to also check all of the email
addresses for correctness before proceeding.
where <svn-repo> is the same repository URL used above and <git-repo-name> is the folder name in the current
directory to clone the repository into. There are a few considerations before using this command:
The --stdlayout flag from above tells Git that you're using a standard layout with trunk, branches, and tags
folders. Subversion repositories with non-standard layouts require you to specify the locations of the trunk
folder, any/all branch folders, and the tags folder. This can be done by following this example: git svn
clone --trunk=/trunk --branches=/branches --branches=/bugfixes --tags=/tags --authors-
file=authors.txt <svn-repo> <git-repo-name>.
This command could take many hours to complete depending on the size of your repo.
To cut down the conversion time for large repositories, the conversion can be run directly on the server
hosting the subversion repository in order to eliminate network overhead.
git svn clone imports the subversion branches (and trunk) as remote branches including subversion tags (remote
branches prefixed with tags/). To convert these to actual branches and tags, run the following commands on a
Linux machine in the order they are provided. After running them, git branch -a should show the correct branch
names, and git tag -l should show the repository tags.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 130
git for-each-ref refs/remotes/origin/tags | cut -d / -f 5- | grep -v @ | while read tagname; do git
tag $tagname origin/tags/$tagname; git branch -r -d origin/tags/$tagname; done
git for-each-ref refs/remotes | cut -d / -f 4- | grep -v @ | while read branchname; do git branch
"$branchname" "refs/remotes/origin/$branchname"; git branch -r -d "origin/$branchname"; done
The conversion from svn to Git is now complete! Simply push your local repo to a server and you can continue to
contribute using Git as well as having a completely preserved version history from svn.
cd
git clone git://repo.or.cz/fast-export.git
git init git_repo
cd git_repo
~/fast-export/hg-fast-export.sh -r /path/to/old/mercurial_repo
git checkout HEAD
To put your solution into Git by using Git-TF follow these steps:
Download Git-TF
You can download (and install) Git-TF from Codeplex: Git-TF @ Codeplex
The --deep switch is the keeyword to note as this tells Git-Tf to copy your checkin-history. You now have a local git
repository in the folder from which you called your cloe command from.
Cleanup
Add a .gitignore file. If you are using Visual Studio the editor can do this for you, otherwise you could do this
manually by downloading a complete file from github/gitignore.
RemoveTFS source control bindings from solution (remove all *.vssscc files). You could also modify your
solution file by removing the GlobalSection(TeamFoundationVersionControl)......EndClobalSection
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 131
Complete your conversion by committing and pushing your local repository to your remote.
git add .
git commit -a -m "Coverted solution source control from TFVC to Git"
Examples
To migrate a svn repository with the standard layout (ie. branches, tags and trunk at the root level of the
repository):
$ svn2git http://svn.example.com/path/to/repo
In case you do not want to migrate (or do not have) branches, tags or trunk you can use options --notrunk, --
nobranches, and --notags.
To reduce the space required by your new repository you may want to exclude any directories or files you once
added while you should not have (eg. build directory or archives):
Post-migration optimization
If you already have a few thousand of commits (or more) in your newly created git repository, you may want to
reduce space used before pushing your repository on a remote. This can be done using the following command:
$ git gc --aggressive
Note: The previous command can take up to several hours on large repositories (tens of thousand of commits
and/or hundreds of megabytes of history).
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 132
Chapter 37: Show
Section 37.1: Overview
git show shows various Git objects.
For commits:
Command Description
git show shows the previous commit
git show @~3 shows the 3rd-from-last commit
Command Description
git show @~3: shows the project root directory as it was 3 commits ago (a tree)
git show @~3:src/program.js shows src/program.js as it was 3 commits ago (a blob)
git show @:a.txt @:b.txt shows a.txt concatenated with b.txt from current commit
For tags:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 133
Chapter 38: Resolving merge conflicts
Section 38.1: Manual Resolution
While performing a git merge you may find that git reports a "merge conflict" error. It will report to you which files
have conflicts, and you will need to resolve the conflicts.
A git status at any point will help you see what still needs editing with a helpful message like
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
no changes added to commit (use "git add" and/or "git commit -a")
Git leaves markers in the files to tell you where the conflict arose:
In order to resolve the conflicts, you must edit the area between the <<<<<< and >>>>>>> markers appropriately,
remove the status lines (the <<<<<<<, >>>>>>>, and ======== lines) completely. Then git add index.html to mark
it resolved and git commit to finish the merge.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 134
Chapter 39: Bundles
Section 39.1: Creating a git bundle on the local machine and
using it on another
Sometimes you may want maintain versions of a git repository on machines that have no network connection.
Bundles allow you to package git objects and references in a repository on one machine and import those into a
repository on another.
Somehow transfer the changes_between_tags.bundle file to the remote machine; e.g., via thumb drive. Once you
have it there:
The reverse is also possible. Once you've made changes on the remote repository you can bundle up the deltas; put
the changes on, e.g., a thumb drive, and merge them back into the local repository so the two can stay in sync
without requiring direct git, ssh, rsync, or http protocol access between the machines.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 135
Chapter 40: Display commit history
graphically with Gitk
Section 40.1: Display commit history for one file
gitk path/to/myfile
gitk v2.3..
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 136
Chapter 41: Bisecting/Finding faulty
commits
Section 41.1: Binary search (git bisect)
git bisect allows you to find which commit introduced a bug using a binary search.
Start by bisecting a session by providing two commit references: a good commit before the bug, and a bad commit
after the bug. Generally, the bad commit is HEAD.
git starts a binary search: It splits the revision in half and switches the repository to the intermediate revision.
Inspect the code to determine if the revision is good or bad:
git will continue to run the binary search on each remaining subset of bad revisions depending on your
instructions. git will present a single revision that, unless your flags were incorrect, will represent exactly the
revision where the bug was introduced.
Afterwards remember to run git bisect reset to end the bisect session and return to HEAD.
If you have a script that can check for the bug, you can automate the process with:
Where [script] is the path to your script and [arguments] is any arguments that should be passed to your script.
Running this command will automatically run through the binary search, executing git bisect good or git bisect
bad at each step depending on the exit code of your script. Exiting with 0 indicates good, while exiting with 1-124,
126, or 127 indicates bad. 125 indicates that the script cannot test that revision (which will trigger a git bisect
skip).
This will tell git that master is a broken revision (or the first broken version) and old-rel is the last known version.
Git will now check out a detached head in the middle of both commits. Now, you can do your testing. Depending on
whether it works or not issue
or
. In case this commit cannot be tested, you can easily git reset and test that one, git willl take care of this.
After a few steps git will output the faulty commit hash.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 138
Chapter 42: Blaming
Parameter Details
filename Name of the file for which details need to be checked
-f Show the file name in the origin commit
-e Show the author email instead of author name
-w Ignore white spaces while making a comparison between child and parent's version
-L start,end Show only the given line range Example: git blame -L 1,2 [filename]
--show-stats Shows additional statistics at end of blame output
-l Show long rev (Default: off)
-t Show raw timestamp (Default: off)
-reverse Walk history forward instead of backward
-p, --porcelain Output for machine consumption
-M Detect moved or copied lines within a file
In addition to -M, detect lines moved or copied from other files that were modified in the same
-C
commit
-h Show the help message
-c Use the same output mode as git-annotate (Default: off)
-n Show the line number in the original commit (Default: off)
line number
/regex/
Multiple line ranges can be specified, and overlapping ranges are allowed.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 139
// Shows the author email and commit per line of specified
git blame -e test.c file
will show the file with each line annotated with the commit that last modified it.
git blame -w
will ignore whitespace-only changes to find where the line really came from.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 140
Chapter 43: Git revisions syntax
Section 43.1: Specifying revision by object name
$ git show dae86e1950b1277e545cee180551750029cfe735
$ git show dae86e19
You can specify revision (or in truth any object: tag, tree i.e. directory contents, blob i.e. file contents) using SHA-1
object name, either full 40-byte hexadecimal string, or a substring that is unique to the repository.
You can specify revision using a symbolic ref name, which includes branches (for example 'master', 'next', 'maint'),
tags (for example 'v1.0', 'v0.6.3-rc2'), remote-tracking branches (for example 'origin', 'origin/master'), and special
refs such as 'HEAD' for current branch.
If the symbolic ref name is ambiguous, for example if you have both branch and tag named 'fix' (having branch and
tag with the same name is not recommended), you need to specify the kind of ref you want to use:
'HEAD' names the commit on which you based the changes in the working tree, and is usually the symbolic name
for the current branch. Many (but not all) commands that take revision parameter defaults to 'HEAD' if it is missing.
A ref, usually a branch or HEAD, followed by the suffix @ with an ordinal specification enclosed in a brace pair (e.g.
{1}, {15}) specifies the n-th prior value of that ref in your local repository. You can check recent reflog entries with
git reflog command, or --walk-reflogs / -g option to git log.
$ git reflog
08bb350 HEAD@{0}: reset: moving to HEAD^
4ebf58d HEAD@{1}: commit: gitweb(1): Document query parameters
08bb350 HEAD@{2}: pull: Fast-forward
f34be46 HEAD@{3}: checkout: moving from af40944bda352190f05d22b7cb8fe88beb17f3a7 to master
af40944 HEAD@{4}: checkout: moving from master to v2.6.3
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 141
4ebf58d gitweb-docs@{0}: branch: Created from master
Note: using reflogs practically replaced older mechanism of utilizing ORIG_HEAD ref (roughly equivalent to HEAD@{1}).
A ref followed by the suffix @ with a date specification enclosed in a brace pair (e.g. {yesterday}, {1 month 2 weeks
3 days 1 hour 1 second ago} or {1979-02-26 18:30:00}) specifies the value of the ref at a prior point in time (or
closest point to it). Note that this looks up the state of your local ref at a given time; e.g., what was in your local
'master' branch last week.
You can use git reflog with a date specifier to look up exact time where you did something to given ref in the
local repository.
The suffix @{upstream} appended to a branchname (short form <branchname>@{u}) refers to the branch that the
branch specified by branchname is set to build on top of (configured with branch.<name>.remote and
branch.<name>.merge, or with git branch --set-upstream-to=<branch>). A missing branchname defaults to the
current one.
Together with syntax for revision ranges it is very useful to see the commits your branch is ahead of upstream
(commits in your local repository not yet present upstream), and what commits you are behind (commits in
upstream not merged into local branch), or both:
A suffix ^ to a revision parameter means the first parent of that commit object. ^<n> means the <n>-th parent (i.e.
<rev>^ is equivalent to <rev>^1).
A suffix ~<n> to a revision parameter means the commit object that is the <n>-th generation ancestor of the named
commit object, following only the first parents. This means that for example <rev>~3 is equivalent to <rev>^^^. As a
shortcut, <rev>~ means <rev>~1, and is equivalent to <rev>^1, or <rev>^ in short.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 142
This syntax is composable.
To find such symbolic names you can use the git name-rev command:
Note that --pretty=oneline and not --oneline must be used in the following example
A suffix ^ followed by an object type name (tag, commit, tree, blob) enclosed in brace pair (for example
v0.99.8^{commit}) means dereference the object at <rev> recursively until an object of type <type> is found or the
object cannot be dereferenced anymore. <rev>^0 is a short-hand for <rev>^{commit}.
A suffix ^ followed by an empty brace pair (for example v0.99.8^{}) means to dereference the tag recursively until
a non-tag object is found.
Compare
with
A colon (':'), followed by a slash ('/'), followed by a text, names a commit whose commit message matches the
specified regular expression. This name returns the youngest matching commit which is reachable from any ref.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 143
The regular expression can match any part of the commit message. To match messages starting with a string, one
can use e.g. :/^foo. The special sequence :/! is reserved for modifiers to what is matched. :/!-foo performs a
negative match, while :/!!foo matches a literal ! character, followed by foo.
A suffix ^ to a revision parameter, followed by a brace pair that contains a text led by a slash, is the same as the
:/<text> syntax below that it returns the youngest matching commit which is reachable from the <rev> before ^.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 144
Chapter 44: Worktrees
Parameter Details
By default, add refuses to create a new working tree when <branch> is already checked
-f --force
out by another working tree. This option overrides that safeguard.
With add, create a new branch named <new-branch> starting at <branch>, and check out
-b <new-branch> -B <new-branch> into the new working tree. If <branch> is omitted, it defaults to HEAD. By
<new-branch> default, -b refuses to create a new branch if it already exists. -B overrides this safeguard,
resetting <new-branch> to <branch>.
--detach With add, detach HEAD in the new working tree.
By default, add checks out <branch>, however, --no-checkout can be used to suppress
--[no-] checkout
checkout in order to make customizations, such as configuring sparse-checkout.
-n --dry-run With prune, do not remove anything; just report what it would remove.
With list, output in an easy-to-parse format for scripts. This format will remain stable
--porcelain
across Git versions and regardless of user configuration.
-v --verbose With prune, report all removals.
--expire <time> With prune, only expire unused working trees older than <time>.
By adding a worktree, you create a temporary linked working tree to make the emergency fix, remove it when done,
and then resume your earlier coding session:
NOTE: In this example, the fix still is in the emergency-fix branch. At this point you probably want to git merge or
git format-patch and afterwards remove the emergency-fix branch.
To get around this limitation it is possible to perform manual operations directly in the .git reference files.
In this example, the main copy of the repo is living at /home/user/project-main and the secondary worktree is
located at /home/user/project-1 and we want to move it to /home/user/project-2.
Don't perform any git command in between these steps, otherwise the garbage collector might be triggered and
the references to the secondary tree can be lost. Perform these steps from the start until the end without
interruption:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 145
1. Change the worktree's .git file to point to the new location inside the main tree. The file
/home/user/project-1/.git should now contain the following:
gitdir: /home/user/project-main/.git/worktrees/project-2
2. Rename the worktree inside the .git directory of the main project by moving the worktree's directory that
exists in there:
$ mv /home/user/project-main/.git/worktrees/project-1 /home/user/project-
main/.git/worktrees/project-2
/home/user/project-2/.git
$ mv /home/user/project-1 /home/user/project-2
If you have done everything correctly, listing the existing worktrees should refer to the new location:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 146
Chapter 45: Git Remote
Parameter Details
-v, --verbose Run verbosely.
-m <master> Sets head to remote's <master> branch
--mirror=fetch Refs will not be stored in refs/remotes namespace, but instead will be mirrored in the local repo
--mirror=push git push will behave as if --mirror was passed
--no-tags git fetch <name> does not import tags from the remote repo
-t <branch> Specifies the remote to track only <branch>
-f git fetch <name> is run immediately after remote is set up
--tags git fetch <name> imports every tag from the remote repo
-a, --auto The symbolic-ref's HEAD is set to the same branch as the remote's HEAD
-d, --delete All listed refs are deleted from the remote repository
--add Adds <name> to list of currently tracked branches (set-branches)
--add Instead of changing some URL, new URL is added (set-url)
--all Push all branches.
--delete All urls matching <url> are deleted. (set-url)
--push Push URLS are manipulated instead of fetch URLS
The remote heads are not queried first with git ls-remote <name>, cached information is used
-n
instead
--dry-run report what branches will be pruned, but do not actually prune them
--prune Remove remote branches that don't have a local counterpart
It shows the short name (aliases) of each remote handle that you have configured.
$ git remote
premium
premiumPro
origin
To show more detailed information, the --verbose or -v flag can be used. The output will include the URL and the
type of the remote (push or pull):
$ git remote -v
premiumPro https://github.com/user/CatClickerPro.git (fetch)
premiumPro https://github.com/user/CatClickerPro.git (push)
premium https://github.com/user/CatClicker.git (fetch)
premium https://github.com/user/CatClicker.git (push)
origin https://github.com/ud/starter.git (fetch)
origin https://github.com/ud/starter.git (push)
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 147
It takes 2 arguments: an existing remote name (origin, upstream) and the url.
git remote -v
origin https://bitbucket.com/develop/myrepo.git (fetch)
origin https://bitbucket.com/develop/myrepo.git (push)
git remote -v
origin https://localserver/develop/myrepo.git (fetch)
origin https://localserver/develop/myrepo.git (push)
For adding a remote Git repository <url> as an easy short name <name> use
The command git fetch <name> can then be used to create and update remote-tracking branches
<name>/<branch>.
result:
remote origin
Fetch URL: https://localserver/develop/myrepo.git
Push URL: https://localserver/develop/myrepo.git
HEAD branch: master
Remote branches:
master tracked
Local branches configured for 'git pull':
master merges with remote master
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 148
Local refs configured for 'git push':
master pushes to master (up to date)
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 149
Chapter 46: Git Large File Storage (LFS)
Section 46.1: Declare certain file types to store externally
A common workflow for using Git LFS is to declare which files are intercepted through a rules-based system, just
like .gitignore files.
Much of time, wildcards are used to pick certain file-types to blanket track.
When a file matching the above pattern is added them committed, when it is then pushed to the remote, it will be
uploaded separately, with a pointer replacing the file in the remote repository.
After a file has been tracked with lfs, your .gitattributes file will be updated accordingly. Github recommends
committing your local .gitattributes file, rather than working with a global .gitattributes file, to help ensure
you don't have any issues when working with different projects.
For example, to exclude a certain file from LFS fetches be default, create and commit .lfsconfig with the following
contents:
[lfs]
fetchexclude = ReallyBigFile.wav
For Brew,
brew install git-lfs
git lfs install
Often you will also need to do some setup on the service that hosts your remote to allow it to work with lfs. This will
be different for each host, but will likely just be checking a box saying you want to use git lfs.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 150
Chapter 47: Git Patch
Parameter Details
The list of mailbox files to read patches from. If you do not supply this
(<mbox>|<Maildir>)... argument, the command reads from the standard input. If you supply
directories, they will be treated as Maildirs.
Add a Signed-off-by: line to the commit message, using the committer
-s, --signoff
identity of yourself.
-q, --quiet Be quiet. Only print error messages.
Pass -u flag to git mailinfo. The proposed commit log message taken
from the e-mail is re-coded into UTF-8 encoding (configuration variable
-u, --utf8
i18n.commitencoding can be used to specify project’s preferred
encoding if it is not UTF-8). You can use --no-utf8 to override this.
--no-utf8 Pass -n flag to git mailinfo.
When the patch does not apply cleanly, fall back on 3-way merge if the
-3, --3way patch records the identity of blobs it is supposed to apply to and we have
those blobs available locally.
--ignore-date, --ignore-space-change, --
ignore-whitespace, --
whitespace=<option>, -C<n>, -p<n>, -- These flags are passed to the git apply program that applies the patch.
directory=<dir>, --exclude=<path>, --
include=<path>, --reject
By default the command will try to detect the patch format automatically.
This option allows the user to bypass the automatic detection and specify
--patch-format
the patch format that the patch(es) should be interpreted as. Valid
formats are mbox, stgit, stgit-series, and hg.
-i, --interactive Run interactively.
By default the command records the date from the e-mail message as
the commit author date, and uses the time of commit creation as the
--committer-date-is-author-date
committer date. This allows the user to lie about the committer date by
using the same value as the author date.
By default the command records the date from the e-mail message as
the commit author date, and uses the time of commit creation as the
--ignore-date
committer date. This allows the user to lie about the author date by using
the same value as the committer date.
Skip the current patch. This is only meaningful when restarting an
--skip
aborted patch.
-S[<keyid>], --gpg-sign[=<keyid>] GPG-sign commits.
After a patch failure (e.g. attempting to apply conflicting patch), the user
has applied it by hand and the index file stores the result of the
--continue, -r, --resolved application. Make a commit using the authorship and commit log
extracted from the e-mail message and the current index file, and
continue.
When a patch failure occurs, <msg> will be printed to the screen before
exiting. This overrides the standard message informing you to use --
--resolvemsg=<msg>
continue or --skip to handle the failure. This is solely for internal use
between git rebase and git am.
--abort Restore the original branch and abort the patching operation.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 151
2. Run git format-patch <commit-reference> to convert all commits since the commit <commit-reference>
(not including it) into patch files.
For example, if patches should be generated from the latest two commits:
This will create 2 files, one for each commit since HEAD~~, like this:
0001-hello_world.patch
0002-beginning.patch
git am some.patch
git am *.patch
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 152
Chapter 48: Git statistics
Parameter Details
Sort output according to the number of commits per author instead of
-n, --numbered
alphabetic order
-s, --summary Only provide a commit count summary
-e, --email Show the email address of each author
Instead of the commit subject, use some other information to describe each
--format[=<format>] commit. <format> can be any string accepted by the --format option of git
log.
Linewrap the output by wrapping each line at width. The first line of each
-w[<width>[,<indent1>[,<indent2>]]] entry is indented by indent1 number of spaces, and subsequent lines are
indented by indent2 spaces.
Show only commits in the specified revision range. Default to the whole
<revision range>
history until the current commit.
Show only commits that explain how the files matching path came to be.
[--] <path> Paths may need to be prefixed with "-- " to separate them from options or the
revision range.
Section 48.2: Listing each branch and its last revision's date
for k in `git branch -a | sed s/^..//`; do echo -e `git log -1 --pretty=format:"%Cgreen%ci
%Cblue%cr%Creset" $k --`\\t"$k";done | sort
By default, all commit messages are shown but argument --summary or -s skips the messages and gives a list of
authors with their total number of commits.
--numbered or -n changes the ordering from alphabetical (by author ascending) to number of commits descending.
git shortlog -sne #Names along with their email ids and the Number of commits
or
Note: Commits by the same person may not be grouped together where their name and/or email address has
been spelled differently. For example John Doe and Johnny Doe will appear separately in the list. To resolve this,
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 153
refer to the .mailmap feature.
This will give a nice overview of all commits (1 per line) with date, user and commit message.
The --pretty option has many placeholders, each starting with %. All options can be found here
If you have gnu locate or mlocate, this will select only the git dirs:
git shortlog -s
which provides the author names and number of commits by each one.
Additionally, if you want to have the results calculated on all branches, add --all flag to the command:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 154
Chapter 49: git send-email
Section 49.1: Use git send-email with Gmail
Background: if you work on a project like the Linux kernel, rather than make a pull request you will need to submit
your commits to a listserv for review. This entry details how to use git-send email with Gmail.
[sendemail]
smtpserver = smtp.googlemail.com
smtpencryption = tls
smtpserverport = 587
smtpuser = [email protected]
Then on the web: Go to Google -> My Account -> Connected Apps & Sites -> Allow less secure apps -> Switch ON
To create and send updated version (version 2 in this example) of the patch:
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 155
git send-email --compose --no-chain-reply-to --to [email protected] /tmp/ulogd2/
First command will create a serie of mail from patches in /tmp/ulogd2/ with statistic report and second will start
your editor to compose an introduction mail to the patchset. To avoid awful threaded mail series, one can use :
source
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 156
Chapter 50: Git GUI Clients
Section 50.1: gitk and git-gui
When you install Git, you also get its visual tools, gitk and git-gui.
gitk is a graphical history viewer. Think of it like a powerful GUI shell over git log and git grep. This is the
tool to use when you’re trying to find something that happened in the past, or visualize your project’s
history.
Gitk is easiest to invoke from the command-line. Just cd into a Git repository, and type:
Gitk accepts many command-line options, most of which are passed through to the underlying git log
action. Probably one of the most useful is the --all flag, which tells gitk to show commits reachable from
any ref, not just HEAD. Gitk’s interface looks like this:
On the top is something that looks a bit like the output of git log --graph; each dot represents a commit,
the lines represent parent relationships, and refs are shown as colored boxes. The yellow dot represents
HEAD, and the red dot represents changes that are yet to become a commit. At the bottom is a view of
the selected commit; the comments and patch on the left, and a summary view on the right. In between is
a collection of controls used for searching history.
You can access many git related functions via right-click on a branch name or a commit message. For
example checking out a different branch or cherry pick a commit is easily done with one click.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 157
git-gui, on the other hand, is primarily a tool for crafting commits. It, too, is easiest to invoke from the
command line:
$ git gui
On the left is the index; unstaged changes are on top, staged changes on the bottom. You can move
entire files between the two states by clicking on their icons, or you can select a file for viewing by clicking
on its name.
At top right is the diff view, which shows the changes for the currently-selected file. You can stage
individual hunks (or individual lines) by right-clicking in this area.
At the bottom right is the message and action area. Type your message into the text box and click
“Commit” to do something similar to git commit. You can also choose to amend the last commit by
choosing the “Amend” radio button, which will update the “Staged Changes” area with the contents of the
last commit. Then you can simply stage or unstage some changes, alter the commit message, and click
“Commit” again to replace the old commit with a new one.
gitk and git-gui are examples of task-oriented tools. Each of them is tailored for a specific purpose
(viewing history and creating commits, respectively), and omit the features not necessary for that task.
Source: https://git-scm.com/book/en/v2/Git-in-Other-Environments-Graphical-Interfaces
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 159
Chapter 51: Reflog - Restoring commits
not shown in git log
Section 51.1: Recovering from a bad rebase
Suppose that you had started an interactive rebase:
and by mistake, you squashed or dropped some commits that you didn't want to lose, but then completed the
rebase. To recover, do git reflog, and you might see some output like this:
In this case, the last commit, ddddddd (or HEAD@{n+1}) is the tip of your pre-rebase branch. Thus, to recover that
commit (and all parent commits, including those accidentally squashed or dropped), do:
You can then create a new branch at that commit with git checkout -b [branch]. See Branching for more
information.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 160
Chapter 52: TortoiseGit
Section 52.1: Squash commits
The easy way
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 161
Section 52.2: Assume unchanged
If a file is changed, but you don't like to commit it, set the file as "Assume unchanged"
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 162
Revert "Assume unchanged"
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 163
Section 52.3: Ignoring Files and Folders
Those that are using TortioseGit UI click Right Mouse on the file (or folder) you want to ignore -> TortoiseGit
-> Delete and add to ignore list, here you can choose to ignore all files of that type or this specific file -> dialog
will pop out Click Ok and you should be done.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 164
Section 52.4: Branching
For those that are using UI to branch click Right Mouse on repository then Tortoise Git -> Create Branch...
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 165
New window will open -> Give branch a name -> Tick the box Switch to new branch (Chances are you want to
start working with it after branching). -> Click OK and you should be done.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 166
Chapter 53: External merge and ditools
Section 53.1: Setting up KDi3 as merge tool
The following should be added to your global .gitconfig file
[merge]
tool = kdiff3
[mergetool "kdiff3"]
path = D:/Program Files (x86)/KDiff3/kdiff3.exe
keepBackup = false
keepbackup = false
trustExitCode = false
Remember to set the path property to point to the directory where you have installed KDiff3
The one gotcha here is that this cmd property does not accept any weird characters in the path. If your IDE's install
location has weird characters in it (e.g. it's installed in Program Files (x86), you'll have to create a symlink
The one gotcha here is that this cmd property does not accept any weird characters in the path. If your IDE's install
location has weird characters in it (e.g. it's installed in Program Files (x86), you'll have to create a symlink
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 167
Section 53.5: Setting up Beyond Compare
You can set the path to bcomp.exe
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 168
Chapter 54: Update Object Name in
Reference
Section 54.1: Update Object Name in Reference
Use
SYNOPSIS
git update-ref [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] [--create-reflog] <ref>
<newvalue> [<oldvalue>] | --stdin [-z])
General Syntax
1. Dereferencing the symbolic refs, update the current branch head to the new object.
2. Stores the newvalue in ref, after verify that the current value of the ref matches oldvalue.
above syntax updates the master branch head to newvalue only if its current value is oldvalue.
Use -d flag to deletes the named <ref> after verifying it still contains <oldvalue>.
Use --create-reflog, update-ref will create a reflog for each ref even if one would not ordinarily be created.
Use -z flag to specify in NUL-terminated format, which has values like update, create, delete, verify.
Update
Set <ref> to <newvalue> after verifying <oldvalue>, if given. Specify a zero <newvalue> to ensure the ref does not
exist after the update and/or a zero <oldvalue> to make sure the ref does not exist before the update.
Create
Create <ref> with <newvalue> after verifying it does not exist. The given <newvalue> may not be zero.
Delete
Delete <ref> after verifying it exists with <oldvalue>, if given. If given, <oldvalue> may not be zero.
Verify
Verify <ref> against <oldvalue> but do not change it. If <oldvalue> zero or missing, the ref must not exist.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 169
Chapter 55: Git Branch Name on Bash
Ubuntu
This documentation deals with the branch name of the git on the bash terminal. We developers need to find the
git branch name very frequently. We can add the branch name along with the path to the current directory.
PS1 denotes Prompt String 1. It is the one of the prompt available in Linux/UNIX shell. When you open your
terminal, it will display the content defined in PS1 variable in your bash prompt. In order to add branch name to
bash prompt we have to edit the PS1 variable (set value of PS1 in ~/.bash_profile).
git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
export PS1="\u@\h \[\033[32m\]\w\[\033[33m\]\$(git_branch)\[\033[00m\] $ "
This git_branch function will find the branch name we are on. Once we are done with this changes we can navigate
to the git repo on the terminal and will be able to see the branch name.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 170
Chapter 56: Git Client-Side Hooks
Like many other Version Control Systems, Git has a way to fire off custom scripts when certain important actions
occur. There are two groups of these hooks: client-side and server-side. Client-side hooks are triggered by
operations such as committing and merging, while server-side hooks run on network operations such as receiving
pushed commits. You can use these hooks for all sorts of reasons.
$1 -- Name of the remote to which the push is being done (Ex: origin)
$2 -- URL to which the push is being done (Ex: https://://.git)
Information about the commits which are being pushed is supplied as lines to the standard input in the form:
Sample values:
local_ref = refs/heads/master
local_sha1 = 68a07ee4f6af8271dc40caae6cc23f283122ed11
remote_ref = refs/heads/master
remote_sha1 = efd4d512f34b11e3cf5c12433bbedd4b1532716f
Below example pre-push script was taken from default pre-push.sample which was automatically created when a
new repository is initialized with git init
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 171
# Check for WIP commit
commit=`git rev-list -n 1 --grep '^WIP' "$range"`
if [ -n "$commit" ]
then
echo >&2 "Found WIP commit in $local_ref, not pushing"
exit 1
fi
fi
done
exit 0
To enable a hook script, put a file in the hooks subdirectory of your .git directory that is named appropriately
(without any extension) and is executable.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 172
Chapter 57: Git rerere
rerere (reuse recorded resolution) allows you to tell git to remember how you resolved a hunk conflict. This allows
it to be automatically resolved the next time that git encounters the same conflict.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 173
Chapter 58: Change git repository name
If you change repository name on the remote side, such as your github or bitbucket, when you push your exisiting
code, you will see error: Fatal error, repository not found**.
cd projectFolder
git remote -v (it will show previous git url)
git remote set-url origin https://[email protected]/username/newName.git
git remote -v (double check, it will show new git url)
git push (do whatever you want.)
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 174
Chapter 59: Git Tagging
Like most Version Control Systems (VCSs), Git has the ability to tag specific points in history as being important.
Typically people use this functionality to mark release points (v1.0, and so on).
$ git tag
<output follows>
v0.1
v1.3
This will create a local tag with the current state of the branch you are on.
This will create a local tag with the commit-identifier of the branch you are on.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 175
git push origin tag-name
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 176
Chapter 60: Tidying up your local and
remote repository
Section 60.1: Delete local branches that have been deleted on
the remote
To remote tracking between local and deleted remote branches use
git fetch -p
Branches that are no longer being tracked will be in the form below, containing 'gone'
you can then use a combination of the above commands, looking for where 'git branch -vv' returns 'gone' then
using '-d' to delete the branches
git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 177
Chapter 61: di-tree
Compares the content and mode of blobs found via two tree objects.
LearnLoner.com
GoalKicker.com – Git® Notes for Professionals 178