1. Learn Git
    1. Learn Git with Bitbucket Cloud
      1. Create a Git repository
      2. Copy your Git repository and add files
      3. Pull changes from your Git repository on Bitbucket Cloud
      4. Use a Git branch to merge a file
    2. Learn about code review in Bitbucket Cloud
      1. Fork a teammate's repository
      2. Copy your fork and make a change to the repository
      3. Create a pull request
  2. Getting Started
    1. What is version control
      1. Benefits of version control
    2. What is Git
      1. Performance
      2. Security
      3. Flexibility
      4. Version control with Git
    3. Why Git for your organization
      1. Git for developers
      2. Git for marketing
      3. Git for product management
      4. Git for designers
      5. Git for customer support
      6. Git for human resources
      7. Git for anyone managing a budget
    4. Install Git
      1. Install Git on Mac OS X
      2. Install Git on Windows
      3. Install Git on Linux
    5. Setting up a repository
      1. git init
      2. git clone
      3. git config
    6. Saving changes
      1. git add
      2. git commit
      3. git stash
    7. Inspecting a repository
      1. git status
      2. git log
    8. Viewing old commits
      1. Undoing Changes
        1. git checkout
        2. git revert
        3. git reset
        4. git clean
      2. Rewriting history
        1. git commit --amend
        2. git rebase
        3. git rebase -i
        4. git reflog
    9. Collaborating
      1. Syncing
        1. git remote
        2. git fetch
        3. git pull
        4. git push
      2. Making a Pull Request
        1. How it works
        2. Example
        3. Where to go from here
      3. Using Branches
        1. git branch
        2. git checkout
        3. git merge
      4. Comparing Workflows
        1. Centralized Workflow
        2. Feature Branch Workflow
        3. Gitflow Workflow
        4. Forking Workflow
    10. Migrating to Git
      1. SVN to Git - prepping for the migration
        1. For administrators
        2. Basic Git commands
        3. Git Migration Tools
        4. For developers
      2. Migrate to Git from SVN
        1. Prepare
          1. Convert
            1. Synchronize
              1. Share
                1. Migrate
                2. Advanced Tips
                  1. Advanced Git Tutorials
                    1. Merging vs. Rebasing
                      1. Conceptual Overview
                      2. The Golden Rule of Rebasing
                      3. Workflow Walkthrough
                      4. Summary
                    2. Reset, Checkout, and Revert
                      1. Commit-level Operation
                      2. File-level Operations
                      3. Summary
                    3. Advanced Git log
                      1. Formatting Log Output
                      2. Filtering the Commit History
                      3. Summary
                    4. Git Hooks
                      1. Conceptual Overview
                      2. Local Hooks
                      3. Server-side Hooks
                      4. Summary
                    5. Refs and the Reflog
                      1. Hashes
                      2. Refs
                      3. Packed Refs
                      4. Special Refs
                      5. Refspecs
                      6. Relative Refs
                      7. The Reflog
                      8. Summary
                  Search

                  Saving changes

                  git add

                  The git add command adds a change in the working directory to the staging area. It tells Git that you want to include updates to a particular file in the next commit. However, git add doesn't really affect the repository in any significant way—changes are not actually recorded until you run git commit.

                  In conjunction with these commands, you'll also need git status to view the state of the working directory and the staging area.

                  Usage

                  git add <file>

                  Stage all changes in <file> for the next commit.

                  git add <directory>

                  Stage all changes in <directory> for the next commit.

                  git add -p

                  Begin an interactive staging session that lets you choose portions of a file to add to the next commit. This will present you with a chunk of changes and prompt you for a command. Use y to stage the chunk, n to ignore the chunk, s to split it into smaller chunks, e to manually edit the chunk, and q to exit.

                  Discussion

                  The git add and git commit commands compose the fundamental Git workflow. These are the two commands that every Git user needs to understand, regardless of their team’s collaboration model. They are the means to record versions of a project into the repository’s history.

                  Developing a project revolves around the basic edit/stage/commit pattern. First, you edit your files in the working directory. When you’re ready to save a copy of the current state of the project, you stage changes with git add. After you’re happy with the staged snapshot, you commit it to the project history with git commit.

                  Git Tutorial: git add Snapshot

                  The git add command should not be confused with svn add, which adds a file to the repository. Instead, git add works on the more abstract level of changes. This means that git add needs to be called every time you alter a file, whereas svn add only needs to be called once for each file. It may sound redundant, but this workflow makes it much easier to keep a project organized.

                  The Staging Area

                  The staging area is one of Git's more unique features, and it can take some time to wrap your head around it if you’re coming from an SVN (or even a Mercurial) background. It helps to think of it as a buffer between the working directory and the project history.

                  Instead of committing all of the changes you've made since the last commit, the stage lets you group related changes into highly focused snapshots before actually committing it to the project history. This means you can make all sorts of edits to unrelated files, then go back and split them up into logical commits by adding related changes to the stage and commit them piece-by-piece. As in any revision control system, it’s important to create atomic commits so that it’s easy to track down bugs and revert changes with minimal impact on the rest of the project.

                  Example

                  When you’re starting a new project, git add serves the same function as svn import. To create an initial commit of the current directory, use the following two commands:

                  git add .
                  git commit

                  Once you’ve got your project up-and-running, new files can be added by passing the path to git add:

                  git add hello.py
                  git commit

                  The above commands can also be used to record changes to existing files. Again, Git doesn’t differentiate between staging changes in new files vs. changes in files that have already been added to the repository.

                  git commit

                  The git commit command commits the staged snapshot to the project history. Committed snapshots can be thought of as “safe” versions of a project—Git will never change them unless you explicity ask it to. Along with git add, this is one of the most important Git commands.

                  While they share the same name, this command is nothing like svn commit. Snapshots are committed to the local repository, and this requires absolutely no interaction with other Git repositories.

                  Usage

                  git commit

                  Commit the staged snapshot. This will launch a text editor prompting you for a commit message. After you’ve entered a message, save the file and close the editor to create the actual commit. git commit -m "<message>"

                  Commit the staged snapshot, but instead of launching a text editor, use <message> as the commit message.

                  git commit -a

                  Commit a snapshot of all changes in the working directory. This only includes modifications to tracked files (those that have been added with git add at some point in their history).

                  Discussion

                  Snapshots are always committed to the local repository. This is fundamentally different from SVN, wherein the working copy is committed to the central repository. In contrast, Git doesn’t force you to interact with the central repository until you’re ready. Just as the staging area is a buffer between the working directory and the project history, each developer’s local repository is a buffer between their contributions and the central repository.

                  This changes the basic development model for Git users. Instead of making a change and committing it directly to the central repo, Git developers have the opportunity to accumulate commits in their local repo. This has many advantages over SVN-style collaboration: it makes it easier to split up a feature into atomic commits, keep related commits grouped together, and clean up local history before publishing it to the central repository. It also lets developers work in an isolated environment, deferring integration until they’re at a convenient break point.

                  Snapshots, Not Differences

                  Aside from the practical distinctions between SVN and Git, their underlying implementation also follow entirely divergent design philosophies. Whereas SVN tracks differences of a file, Git’s version control model is based on snapshots. For example, an SVN commit consists of a diff compared to the original file added to the repository. Git, on the other hand, records the entire contents of each file in every commit.

                  Git Tutorial: Snapshots, Not Differences

                  This makes many Git operations much faster than SVN, since a particular version of a file doesn’t have to be “assembled” from its diffs—the complete revision of each file is immediately available from Git's internal database.

                  Git's snapshot model has a far-reaching impact on virtually every aspect of its version control model, affecting everything from its branching and merging tools to its collaboration workflows.

                  Example

                  The following example assumes you’ve edited some content in a file called hello.py and are ready to commit it to the project history. First, you need to stage the file with git add, then you can commit the staged snapshot.

                  git add hello.py
                  git commit

                  This will open a text editor (customizable via git config) asking for a commit message, along with a list of what’s being committed:

                  # Please enter the commit message for your changes. Lines starting
                  # with '#' will be ignored, and an empty message aborts the commit.
                  # On branch master
                  # Changes to be committed:
                  # (use "git reset HEAD <file>..." to unstage)
                  #
                  #modified: hello.py

                  Git doesn't require commit messages to follow any specific formatting constraints, but the canonical format is to summarize the entire commit on the first line in less than 50 characters, leave a blank line, then a detailed explanation of what’s been changed. For example:

                  Change the message displayed by hello.py
                  
                  - Update the sayHello() function to output the user's name
                  - Change the sayGoodbye() function to a friendlier message

                  Note that many developers also like to use present tense in their commit messages. This makes them read more like actions on the repository, which makes many of the history-rewriting operations more intuitive.

                  git stash

                  git stash temporarily shelves (or stashes) changes you‘ve made to your working copy so you can work on something else, and then come back and re-apply them later on. Stashing is handy if you need to quickly switch context and work on something else, but you’re mid-way through a code change and aren't quite ready to commit.

                  Stashing your work

                  The git stash command takes your uncommitted changes (both staged and unstaged), saves them away for later use, and then reverts them from your working copy. For example:

                  $ git status
                  On branch master
                  Changes to be committed:
                  
                      new file:   style.css
                  
                  Changes not staged for commit:
                  
                      modified:   index.html
                  
                  $ git stash
                  Saved working directory and index state WIP on master: 5002d47 our new homepage
                  HEAD is now at 5002d47 our new homepage
                  
                  $ git status
                  On branch master
                  nothing to commit, working tree clean

                  At this point you‘re free to make changes, create new commits, switch branches, and perform any other Git operations; then come back and re-apply your stash when you’re ready.

                  Note that the stash is local to your Git repository; stashes are not transferred to the server when you push.

                  Re-applying your stashed changes

                  You can reapply previously stashed changes with git stash pop:

                  $ git status
                  On branch master
                  nothing to commit, working tree clean
                  $ git stash pop
                  On branch master
                  Changes to be committed:
                  
                      new file:   style.css
                  
                  Changes not staged for commit:
                  
                      modified:   index.html
                  
                  Dropped refs/stash@{0} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)

                  Popping your stash removes the changes from your stash and reapplies them to your working copy.

                  Alternatively, you can reapply the changes to your working copy and keep them in your stash with git stash apply:

                  $ git stash apply
                  On branch master
                  Changes to be committed:
                  
                      new file:   style.css
                  
                  Changes not staged for commit:
                  
                      modified:   index.html

                  This is useful if you want to apply the same stashed changes to multiple branches.

                  Now that you know the basics of stashing, there is one caveat with git stash you need to be aware of: by default Git won't stash changes made to untracked or ignored files.

                  Stashing untracked or ignored files

                  By default, running git stash will stash:

                  • changes that have been added to your index (staged changes)
                  • changes made to files that are currently tracked by Git (unstaged changes)

                  But it will not stash:

                  • new files in your working copy that have not yet been staged
                  • files that have been ignored

                  So if we add a third file to our example above, but don‘t stage it (i.e. we don’t run git add), git stash won't stash it.

                  $ script.js
                  
                  $ git status
                  On branch master
                  Changes to be committed:
                  
                      new file:   style.css
                  
                  Changes not staged for commit:
                  
                      modified:   index.html
                  
                  Untracked files:
                  
                      script.js
                  
                  $ git stash
                  Saved working directory and index state WIP on master: 5002d47 our new homepage
                  HEAD is now at 5002d47 our new homepage
                  
                  $ git status
                  On branch master
                  Untracked files:
                  
                      script.js

                  Adding the -u option (or --include-untracked) tells git stash to also stash your untracked files:

                  $ git status
                  On branch master
                  Changes to be committed:
                  
                      new file:   style.css
                  
                  Changes not staged for commit:
                  
                      modified:   index.html
                  
                  Untracked files:
                  
                      script.js
                  
                  $ git stash -u
                  Saved working directory and index state WIP on master: 5002d47 our new homepage
                  HEAD is now at 5002d47 our new homepage
                  
                  $ git status
                  On branch master
                  nothing to commit, working tree clean

                  You can include changes to ignored files as well by passing the -a option (or --all) when running git stash.

                  Managing multiple stashes

                  You aren't limited to a single stash. You can run git stash several times to create multiple stashes, and then use git stash list to view them. By default, stashes are identified simply as a “WIP” – work in progress – on top of the branch and commit that you created the stash from. After a while it can be difficult to remember what each stash contains:

                  $ git stash list
                  stash@{0}: WIP on master: 5002d47 our new homepage
                  stash@{1}: WIP on master: 5002d47 our new homepage
                  stash@{2}: WIP on master: 5002d47 our new homepage

                  To provide a bit more context, it's good practice to annotate your stashes with a description, using git stash save "message":

                  $ git stash save "add style to our site"
                  Saved working directory and index state On master: add style to our site
                  HEAD is now at 5002d47 our new homepage
                  
                  $ git stash list
                  stash@{0}: On master: add style to our site
                  stash@{1}: WIP on master: 5002d47 our new homepage
                  stash@{2}: WIP on master: 5002d47 our new homepage

                  By default, git stash pop will re-apply the most recently created stash: stash@{0}

                  You can choose which stash to re-apply by passing its identifier as the last argument, for example:

                  $ git stash pop stash@{2}

                  Viewing stash diffs

                  You can view a summary of a stash with git stash show:

                  $ git stash show
                   index.html | 1 +
                   style.css | 3 +++
                   2 files changed, 4 insertions(+)

                  Or pass the -p option (or --patch) to view the full diff of a stash:

                  $ git stash show -p
                  diff --git a/style.css b/style.css
                  new file mode 100644
                  index 0000000..d92368b
                  --- /dev/null
                  +++ b/style.css
                  @@ -0,0 +1,3 @@
                  +* {
                  +  text-decoration: blink;
                  +}
                  diff --git a/index.html b/index.html
                  index 9daeafb..ebdcbd2 100644
                  --- a/index.html
                  +++ b/index.html
                  @@ -1 +1,2 @@
                  +<link rel="stylesheet" href="style.css"/>

                  Partial stashes

                  You can also choose to stash just a single file, a collection of files, or individual changes from within files. If you pass the -p option (or --patch) to git stash, it will iterate through each changed “hunk” in your working copy and ask whether you wish to stash it:

                  $ git stash -p
                  diff --git a/style.css b/style.css
                  new file mode 100644
                  index 0000000..d92368b
                  --- /dev/null
                  +++ b/style.css
                  @@ -0,0 +1,3 @@
                  +* {
                  +  text-decoration: blink;
                  +}
                  Stash this hunk [y,n,q,a,d,/,e,?]? y
                  diff --git a/index.html b/index.html
                  index 9daeafb..ebdcbd2 100644
                  --- a/index.html
                  +++ b/index.html
                  @@ -1 +1,2 @@
                  +<link rel="stylesheet" href="style.css"/>
                  Stash this hunk [y,n,q,a,d,/,e,?]? n

                  You can hit ? for a full list of hunk commands. Commonly useful ones are:

                  CommandDescription
                  /search for a hunk by regex
                  ?help
                  ndon't stash this hunk
                  qquit (any hunks that have already been selected will be stashed)
                  ssplit this hunk into smaller hunks
                  ystash this hunk

                  There is no explicit “abort” command, but hitting CTRL-C(SIGINT) will abort the stash process.

                  Creating a branch from your stash

                  If the changes on your branch diverge from the changes in your stash, you may run into conflicts when popping or applying your stash. Instead, you can use git stash branch to create a new branch to apply your stashed changes to:

                  $ git stash branch add-style stash@{1}
                  Switched to a new branch 'add-stylesheet'
                  On branch add-stylesheet
                  Changes to be committed:
                  
                      new file:   style.css
                  
                  Changes not staged for commit:
                  
                      modified:   index.html
                  
                  Dropped refs/stash@{1} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)

                  This checks out a new branch based on the commit that you created your stash from, and then pops your stashed changes onto it.

                  Cleaning up your stash

                  If you decide you no longer need a particular stash, you can delete it with git stash drop:

                  $ git stash drop stash@{1}
                  Dropped stash@{1} (17e2697fd8251df6163117cb3d58c1f62a5e7cdb)

                  Or you can delete all of your stashes with:

                  $ git stash clear

                  How git stash works

                  If you just wanted to know how use git stash, you can stop reading here. But if you're curious about how Git (and git stash) works under the hood, read on!

                  Stashes are actually encoded in your repository as commit objects. The special ref at .git/refs/stash points to your most recently created stash, and previously created stashes are referenced by the stash ref's reflog. This is why you refer to stashes by stash@{n}: you're actually referring to the nth reflog entry for the stash ref. Since a stash is just a commit, you can inspect it with git log:

                  $ git log --oneline --graph stash@{0}
                  *-.   953ddde WIP on master: 5002d47 our new homepage
                  |\ \ 
                  | | * 24b35a1 untracked files on master: 5002d47 our new homepage
                  | * 7023dd4 index on master: 5002d47 our new homepage
                  |/ 
                  * 5002d47 our new homepage

                  Depending on what you stashed, a single git stash operation creates either two or three new commits. The commits in the diagram above are:

                  • stash@{0}, a new commit to store the tracked files that were in your working copy when you ran git stash
                  • stash@{0}'s first parent, the pre-existing commit that was at HEAD when you ran git stash
                  • stash@{0}'s second parent, a new commit representing the index when you ran git stash
                  • stash@{0}'s third parent, a new commit representing untracked files that were in your working copy when you ran git stash. This third parent only created if:
                    • your working copy actually contained untracked files; and
                    • you specified the --include-untracked or --all option when invoked git stash.

                  When you run git stash pop, the changes from the commits above are used to update your working copy and index, and the stash reflog is shuffled to remove the popped commit. Note that the popped commits aren't immediately deleted, but do become candidates for future garbage collection.