Git

Git notes

Branch Management

Note: in most cases, remote_name will be origin

To delete a local branch

Use git branch -d <branch> to delete a local branch

To delete a remote branch

Use git push <remote_name> -d <branch>

To delete a local remote tracking branch

git branch --delete --remotes <remote_name>/<branch>
git branch -dr <remote_name>/<branch> # Shorter

To push local branch to remote

git push -u <remote_name> <branch> will push <branch> to remote by creating a new branch on remote_name and setting local branch to track remote branch on remote_name

Note: -u option is the shortcut for the --set-upstream option (e.g., git push --set-upstream origin master – remember, origin is an alias to the remote)

To pull and track a remote branch

git checkout --track <remote_name>/<branch>: this command will create a local branch named branch, tracking the remote branch <remote/daves_branch

Note: --track is shorthand for git checkout -b [branch] [remotename]/[branch] where [remotename] is origin in this case and [branch] is twice the same, daves_branch in this case

To create a new branch off of the current branch

git checkout -b <branch>

To print what origin points to

origin is an alias on your system for a particular remote repository

git remote show origin

References

  • https://stackoverflow.com/questions/2003505/how-do-i-delete-a-git-branch-locally-and-remotely
  • https://stackoverflow.com/questions/9537392/git-fetch-remote-branch

File management

The “index” holds a snapshot of the content of the working tree, and it is this snapshot that is taken as the contents of the next commit. Thus after making any changes to the working tree, and before running the commit command, you must use the add command to add any new or modified files to the index.

To add all modified files to the index

git add .

To add a specific file or directory to the index

git add <filename>

To remove file matching pathspec from the index

git rm --cached <filename>

Stashing

git stash can be used to “stash” some changes so that they are no longer in your working tree. This allows you to checkout other branches without having to add changes to the index. Usually, this is used when you begin to work on some branch and then realise you are working on the wrong branch. You can use git stash to “stash” these changes (out of the working tree), checkout to the appropriate branch, and apply the stashed changes.

git stash # to save your un-committed changes in a "stash"
git checkout <branch> # to change to correct branch
git stash list # to list stashes
git stash apply stash@{12} # to apply some stash to current branch (in this case its stash `12`)
git stash drop stash@{0} # to remove from stash list
git stash pop stash@{1} # to apply selected stash and drop it from stash list

Alternative workaround:

  1. Make a commit with those desired changes on current “wrong” branch
  2. Checkout to the branch you want those changes to be on.
  3. From that branch git cherry-pick 23h123kjb (replace 23h123kjb with the hash found in the Git log specific to the commit you want to bring in)

References

  • https://stackoverflow.com/questions/3689838/whats-the-difference-between-head-working-tree-and-index-in-git
  • https://dzone.com/articles/beyond-beginning-git-working-tree-index-and-head
  • https://stackoverflow.com/questions/37417792/apply-stash-to-different-branch/41978867

Git Working Tree, Index, and HEAD

The “working tree” refers to the directory (and its files and subdirectories) on your file system that is associated with a repository.

The “index” refers to where you place files that you want to commit to the git repository. The index itself is not the git repository, instead it can be seen as a staging ground for files that you want to commit. Before you can run a git commit, you need to first place the files in the git index by using git add. You can also use the git status command which will return all the files in your working directory which have been added to the git index.

HEAD is a pointer to the branch or commit that you last checked out and which will be the parent of a new commit if you make it. For instance, if you’re on the master branch, then HEAD will point to master, and when you commit, that new commit will be a descendent of the revision that master pointed to, and master will be updated to point to the new commit. If the branch commit history is a linked list, then HEAD would be the head of the linked list (where the head of the linked list is the latest commit).

Reverting Changes

git reset [--soft | --mixed [-N] | --hard | --merge | --keep]

soft reset

When using git reset --soft HEAD~1 you will remove the last commit from the current branch, but the file changes will stay in your working tree. Also the changes will stay on your index, so following with a git commit will create a commit with the exact same changes as the commit you “removed” before.

mixed reset

This is the default mode and quite similar to soft. When “removing” a commit with git reset HEAD~1 you will still keep the changes in your working tree but not on the index; so if you want to “redo” the commit, you will have to add the changes (git add) before commiting.

hard reset

When using git reset --hard HEAD~1 you will lose all uncommited changes in addition to the changes introduced in the last commit. The changes won’t stay in your working tree so doing a git status command will tell you that you don’t have any changes in your repository.

References

  • https://stackoverflow.com/questions/24568936/what-is-difference-between-git-reset-hard-head1-and-git-reset-soft-head

Merging

To merge a branch foo into bar:

git checkout bar
git merge foo

Creating a repository

origin: when you clone a repository for the first time origin is a default alias given to the original remote repository url that you clone, from where you want to push and pull changes. By saying git push origin <branch_name>, you are saying to push to the original repository.

master: this is the name of the default branch that Git creates for you when first create a repository. In most cases, master means “the main branch”. It’s the branch that represents production code, and that all other branches come from and generally eventually rejoin.

  1. git init: creates an empty Git repository or re-initialize an existing one (basically a .git directory with subdirectories for objects, refs/heads, refs/tags, and template files. An initial HEAD file that references the HEAD of the master branch is also created)
  2. git add .: adds all file contents to the “index” (the index holds a snapshot of the content of the working tree, and it is this snapshot that is taken as the contents of the next commit)
  3. git commit -m "first commit": create a new commit containing the current contents of the index and the given log message describing the changes. The new commit is a direct child of HEAD, usually the tip of the current branch, and the branch is updated to point to it
  4. git remote add origin https://github.com/gutucristian/probable-robot.git: creates a new remote called origin located at https://github.com/gutucristian/probable-robot.git. Once you do this, in your push and pull commands, you can use origin instead of typing out the whole URL
  5. git push -u origin master: sets local master branch to “track” origin and pushes master’s working tree to remote defined by origin. (equivalent command: git push --set-upstream origin master)

Tracking branches are local branches that have a direct relationship to a remote branch. If you’re on a tracking branch and type git push, Git automatically knows which server and branch to push to. Also, running git pull while on one of these branches fetches all the remote references and then automatically merges in the corresponding local branch.

References

  • https://stackoverflow.com/questions/4693588/what-is-a-tracking-branch

Miscellaneous

To modify or “ammend” the latest commit message

git commit --amend -m "new commit message"

Git bisect

Uses a binary search algorithm to find which commit in your project’s history introduced a bug.

You use it by first telling it a “bad” commit that is known to contain the bug, and a “good” commit that is known to be before the bug was introduced. Then git bisect picks a commit between those two endpoints and asks you whether the selected commit is “good” or “bad”. It continues narrowing down the range until it finds the exact commit that introduced the change.

If the search range is of N commits, we should expect to test 1 + log2(N) commits with git bisect instead of roughly N / 2 commits with a linear search.

References

  • https://stackoverflow.com/questions/4713088/how-to-use-git-bisect
Written on March 15, 2020