A practical introduction to git
					
						Anna Kennedy
					
					
				
				
					Overview
					
							- Version control
 
							- Git concepts
 
							- Using git locally
 
							- Using git with a (Gitlab) remote
 
							- Undoing mistakes
 
							- Branches
 
							- Caring for your commit history
 
					
					
				
				
					Version control
					
							- Version control means that we keep a history of all the changes made in a set of documents.
 
							- Git is one example of a version control system
 
							- Pre-version control:
                
              
 	
							- CVS / SVN:
                
							    - Centralised storage with revision history
 
                
               	
							- Git:
                
              
 	
					
				
				
					SVN
          Centralised storage with revision history
					
              - client-server model
 
              - central server houses master repo
 
              - developer laptop is the client
 
              - check-out -> modify -> check-in
 
              - Advantages / disadvantages
 
              - + simple system
 
              - - difficult to work offline
 
              - - difficult to work collaboratively
 
              - - advanced functionality quite hard to get right
 
					
				
				
					Git
          Distributed version control
					
							- every copy of the project is a full repository
 
              - Advantages / disadvantages
 
							- - steep learning curve
 
							- + save changes locally when working offline
 
							- + branching
 
							- + merging
 
							- + every copy is a full backup
 
							- + very fast
 
					
				
				
				
					Projects in git
					
							- Any directory can be brought under git's control
 
							- both new and existing projects
 
							- git init initialises a directory with a .git subdir
 
							
							  - This directory is now a local git repository
 
                - The .git folder contains metadata about the project
 
							  - To remove a project from git, simply delete the .git folder
 
              
					
				
  
				
					Exercise: Initialise a new project in git
					
							- Make a new directory and move into it
 
							- Initialise the directory as a git repository
 
            
            
$ mkdir myproject
$ cd myproject
$ git init  
  Initialized empty Git repository in /home/myname/projects/myproject
$ ls -la
  drwxr-xr-x 4096 Apr  5 09:54 .
  drwxr-xr-x 4096 Apr  4 12:40 ..
  drwxr-xr-x 4096 Apr  5 08:13 .git
           
					
				
				
					Configure global git variables
					
						- Git requires that version history is associated with users
 
						- Thus we need to set name and email as global variables
 
						- Trying to use git without this results in the following annoying message:
 
					
          
  Your name and email address were configured automatically based
  on your username and hostname. Please check that they are accurate.
  You can suppress this message by setting them explicitly:
  $  git config --global user.name "Your Name"
  $  git config --global user.email you@example.com
          
					
				
				
					Exercise: Check / set your name and email settings
					
							- Use git config -l to see if you've already set your name and email address
 
							- If you need to set them, use
 
           
   
           
$ git config --global user.name "Your Name"
$ git config --global user.email you@example.com
          
					
				
				
					Checking the current status
					
						- Running git status at any point shows the current state of the directory
 
						- It also often gives hints about how to proceed or undo steps
 
					
          
$ git init  
  Initialized empty Git repository in /home/myname/projects/myproject
$ git status
  On branch master
  Initial commit
  nothing to commit (create/copy files and use "git add" to track)
          
					
				
				
					Getting help
					
						- Access the man pages on the command-line like:
 
					
          
$ git help
  The most commonly used git commands are:
   add        Add file contents to the index
   branch     List, create, or delete branches
   checkout   Checkout a branch or paths to the working tree
$ git help add
  NAME
       git-add - Add file contents to the index
  SYNOPSIS
       git add [-n] [-v] [-f] [-i] [-p] [--] [...]
          
					
				
				
					Adding files to the project
					
							- git add filename to add files to staging
 
							- git add . to add everything
 
					
				
 
				
					Exercise: Add files to the project
					
							- Make a file inside the directory "helloworld.txt"
 
							- Add this file to git
 
            
$ vim helloworld.txt
$ git status
  On branch master
    Untracked files:
    (use "git add file..." to include in what will be committed)
      helloworld.txt
$ git add helloworld.txt
$ git status
  On branch master
  Changes to be committed:
    (use "git reset HEAD file..." to unstage)
       new file: helloworld.txt
              
					 
				
				
					Committing the changes to the local repo
					
							- After a file is added to staging, we then have to commit the changes
 
							- git commit and then enter commit message on the next screen
 
							- git commit -m "commit message" to do both steps at once
 
					
				
 
				
					Exercise: Commit the changes to your local repo
					
								- Commit this file to your local repository
 
                
$ git commit -m "First commit"
$ git status
On branch master
nothing to commit, working directory clean
                
					
				
				
					Basic git rhythm
					
								- Make changes
 
	  						- Stage the changes with git add
 
	  						- Commit the changes with git commit
 
					
				
				
					View commit history
					
						- git log shows a history of commits
 
						- git log -p shows what has changed with each commit
 
						- git log -2 only shows the last two commits
 
					
            
$ git log -p
commit 320a8f00a4a0de7c9b3f39851d3bc164d0769697
Author: myname myname@ak-rl.example.com
Date:   Mon Apr 4 12:52:23 2016 +0200
    First commit
diff --git a/file1.txt b/file1.txt
new file mode 100644
index 0000000..907b308
--- /dev/null
+++ b/file1.txt
@@ -0,0 +1 @@
+Hello everyone!
                
					
				
				
					A little more about commits
					
							- Commits are basically snapshots
 
							- Each commit is identified by a unique hash
 
							- The most recent commit is called HEAD
 
							- The two before that are called HEAD~ and HEAD~2
 
							- We can use both the reference number and the HEAD notation to refer to previous commits
 
					
          
$ git log 
commit 320a8f00a4a0de7c9b3f39851d3bc164d0769697
Author: myname myname@ak-rl.example.com
Date:   Mon Apr 4 12:52:23 2016 +0200
    First commit
                
				
 				
					Amend the commit message
					
							- If you accidentally did a commit with a mistake in the commit message
 
							- git commit --amend lets you change it 
 
					
				
 
				
					Exercise: Edit your most recent commit
					
								- Edit your most recent commit message
 
                
$ git commit --amend
                
                
Allow user login
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
                
					
				
				
					Exercise: Make and view a more interesting commit history
					
					  - So far we literally only have one commit - let's make a bit more to work with
 
					  - Make two more files, and commit them
 
					  - Edit one file, and commit that
 
					  - Make two files and only commit one of them
 
					  - Now commit the other one
 
					  - Use git log and git status to follow the history as you go
 
					
				
				
					Comparing files
					
						- git diff compares current files with the latest committed version
 
						- After you've made a change to a file, but before it's committed
 
						- Use 'git diff' to see what the difference between the files is
 
					
            
$ echo "Pleased to meet you all." >> helloworld.txt
$ git diff
diff --git a/file1.txt b/file1.txt
index 404c772..2d48565 100644
--- a/file1.txt
+++ b/file1.txt
@@ -1,2 +1,3 @@
Hello everyone!
+Pleased to meet you all.
                
					
				
				
					Exercise: Compare files
					
              - Make a change to a file
 
						  - Use 'git diff' to see what the difference between the file now and the last committed version
 
					
            
$ git diff
diff --git a/file1.txt b/file1.txt
index 404c772..2d48565 100644
--- a/file1.txt
+++ b/file1.txt
@@ -1,2 +1,3 @@
Hello everyone!
+Pleased to meet you all.
                
					
				
				
					Stashing your work
					
								- We like to try and keep our commits meaningful (more on this later)
 
								- but if you're in the middle of working on something and you need to pause or switch branches
 
								- you can save your work-in-progress state with git stash
 
								- Can stash multiple events
 
								- git stash list to view them
 
								- git stash apply to pick up your most recent stash
 
					
				
				
					Exercise: Stashing your work
					
								- Make some changes to a file
 
								- Stash your changes
 
								- View the stash list
 
								- Verify the directory is at the state of the latest commit
 
								- Apply the stash to regain your work in progress
 
					
            
$ git stash
  Saved working directory and index state WIP on master: e99a3ac Allow user login
  HEAD is now at e99a3ac Latest hegnar configs
$ git stash list
  stash@{0}: WIP on master: e99a3ac Allow user login
            
				
				
				
					Using a remote repository
					
							- So far we only used our local repository
 
							- If we're interested in collaboration or backups, we need to look at communicating with a remote repository
 
							- For this course, our remote is housed in Gitlab
 
							- Otherwise the remote could be
 
							
							  - plain git
 
							  - gitolite
 
							  - Gitorious
 
                - Github
 
              
					
				
				
					Gitlab
					
							- Gitlab provides a web-gui frontend
 
							- Lots of useful collaborative and exploratory features
 
             
					
				
				
					Creating a remote in Gitlab
					
            
							- Pretty straightforwards to create a new remote in Gitlab
 
             
            
				
				
					Exercise: Create a new remote repository
					
							- Within the Gitlab UI, make a new project
 
							- Name your project, leave it as private
 
							- Notice that it tells you how to proceed!
 
  
							- Within your local repository, tell git where the remote is:
 
                
$ git remote add origin git@gitlab.example.com:myname/myprojectname.git
  # Set a new remote
                
					
				
				
					Pushing changes from the local to the remote repo
					
            
							- So far all our work is only in our local repository
 
							- Use git push to send our commits to the remote repository
 
							- The first time we do this we need to set the upstream branch
 
							- origin is git's default name for the remote repo
 
             
                
$ git push -u origin master
  Counting objects: 5, done.
  Delta compression using up to 4 threads.
  Compressing objects: 100% (5/5), done.
  Writing objects: 100% (5/5), 721 bytes | 0 bytes/s, done.
  Total 5 (delta 2), reused 0 (delta 0)
  To git@gitlab.example.com:myname/myproject.git
     e99a3ac..f91ed8c  master -> master
                
          
				
				
					Exercise: Push changes from the local to the remote repo
					
            
							- Use git push to send your commits to the remote repository
 
							- The first time we do this we need to set the upstream branch with -u
 
							- You should see your files in Gitlab now
 
             
                
$ git push -u origin master
  Counting objects: 5, done.
  Delta compression using up to 4 threads.
  Compressing objects: 100% (5/5), done.
  Writing objects: 100% (5/5), 721 bytes | 0 bytes/s, done.
  Total 5 (delta 2), reused 0 (delta 0)
  To git@gitlab.example.com:myname/myproject.git
     e99a3ac..f91ed8c  master -> master
                
            
				
				
					Retrieving changes from the remote
					
								- If changes have been made on the remote, we need to update our local repository to get those changes
 
								- Use git pull to retrieve any changes
 
					
				
				
					Exercise: pulling remote changes
					
							- Edit a file in Gitlab
 
							- Pulled the changes your local repository
 
							- What do git status and git log say?
 
          
$ git pull
  remote: Counting objects: 3, done.
  remote: Compressing objects: 100% (3/3), done.
  remote: Total 3 (delta 2), reused 0 (delta 0)
  Unpacking objects: 100% (3/3), done.
  From gitlab.example.com:myname/myproject
   f91ed8c..3f522c5  master     -> origin/master
  Updating f91ed8c..3f522c5
  Fast-forward
    file1.txt | 3 ++-
    1 file changed, 2 insertions(+), 1 deletion(-)
          
          
				
      	
					Pull behind the scenes
						
							- So far we've done git pull to get the changes from the remote repository
 
							- git pull really means git fetch then git merge
 
							- We'll talk more about merging soon
 
							- Be aware that sometimes doing a fetch and then a merge instead of pull can give you more insight into what git is doing
 
				  	
				
				
					Viewing remotes on the command line
					
            - git remote shows and can amend the remote repository
 
            - This information is also available in .git/config
 
            - origin is just git's default name for the remote
 
          
$ git remote -v
origin  git@gitlab.example.com:anna/testrepository.git (fetch)
origin  git@gitlab.example.com:anna/testrepository.git (push)
          
          
				
				
					Basic git rhythm with remote
					
								- Get updates with git pull
 
								- Make changes
 
	  						- Stage the changes with git add
 
	  						- Commit the changes with git commit
 
	  						- Push the changes to the remote with git push
 
					
				
				
					Basic git rhythm with remote
					
					
				
	
				
					Working collaboratively
					
						- Git is an amazing tool for working collaboratively
 
						- However then we need to start worrying about changes we didn't make
 
						- If you're the sole committer to a repository, things are usually straightforwards
 
						- However in a team, chances are that people will make conflicting changes at times
 
						- Let's take a pragmatic look at two common issues
 
					
				
	
				
					Troubleshooting 1: the push is rejected
					
            
- If you try to git push your changes and see something like:
 
            
$ git push
To git@gitlab.example.com:myname/myproject.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@gitlab.example.com:myname/testrepository.git'
hint: Updates were rejected because the remote contains work that you do not have locally. 
            
            - Then you're trying to push before you've updated your local repo with remote changes.
 
                - Fix this by doing a git pull first
 
            
            
$ git pull
$ git push
          
        
				
				
					Troubleshooting 2: we got a merge conflict
					
            
              - If we try to git pull (git fetch + git merge) and see something like:
 
            
          
Auto-merging file1.txt
CONFLICT (content): Merge conflict in file1.txt
Automatic merge failed; fix conflicts and then commit the result.
          
          - Then we have a merge conflict we need to resolve
 
        
				
				
        	
          Let's see what the problem is:
          
$ git status
Unmerged paths:
  (use "git add ..." to mark resolution)
        both modified:   file1.txt
          
          
$ git diff
  diff --cc file1.txt
  index 528038e,f324c51..0000000
  --- a/file1.txt
  +++ b/file1.txt
  @@@ -1,4 -1,4 +1,8 @@@
  ++<<<<<<< HEAD
   +hello
  ++=======
  + goodbye
  ++>>>>>>> 3911012567a3a5a0432bea090b82b58d74d5aa9d
          
				
				
          
            - Resolution: decide what the file should contain 
 
            - Git writes markers in the file around conflicting sections
 
            - Edit the file (including deleting the markers)
 
            - Add, commit, push.
 
          
          
$ cat file1.txt
  <<<<<<< HEAD
  hello
  =======
  goodbye
  >>>>>>> 3911012567a3a5a0432bea090b82b58d74d5aa9d
$ nano file1.txt
$ git add file1.txt
$ git commit -m "Fixing conflict"
$ git push
          
				
				
					Working collaboratively
					
						- With that in mind, let's move on to using a common repository
 
						- For the purposes of this course, we've set up an example repo in Gitlab for us all to clone
 
						- Then we can experiment with making and resolving conflicts
 
					
				
				
					Cloning an existing repository
					
            - If we want to work on an existing repository, we can either edit the files in Gitlab, or clone the repo locally.
 
            - Editing in the UI tends to only be practical for very small, isolated changes.
 
            - To clone a repo, find the correct URL in Gitlab, displayed ssh/http on the project page.
 
            - SSH needs a key to have been set up, HTTPS needs a username and password.
 
          
          
$ git clone git@gitlab.example.com:myname/myproject.git
or
$ git clone https://gitlab.example.com/myname/myproject.git
          
				
				
					Exercise: Clone a remote
					
            - Clone the example repo to your local directory
 
            - Make a new file, add and commit the changes locally
 
            - If you're working in a group, remember to do git pull to get any changes made by other people
 
            - Push the changes back to the remote
 
            - Did you get any conflicts?
 
            - Verify the new file is visible in Gitlab
 
            
$ git clone git@gitlab.example.com:myname/myproject.git
$ git add ...
$ git commit ...
$ git pull
$ git push
            
          
				
				
					Exercise: resolving issues
					
            - Make a file in the Github UI and commit it
 
            - Without doing a pull, edit the same file locally
 
            - Add and commit the file
 
            - What happens when you try to push it back to the remote?
 
            - Look at git diff and git status
 
            - Do a git pull to get the remote changes
 
            - This should cause a merge conflict
 
            - Edit the file to resolve the conflict
 
            - Now try adding, committing, and pushing again
 
          
				
				
				
					Undoing mistakes
					
            - We're human, and as such we make mistakes
 
            - If you use git regularly, you will screw it all up from time to time
 
            - Let's look at how to un-screw it up so it's not so terrifying next time
 
          
				
				
					Git reset to undo local changes
					
						- git reset file1.txt un-stages a file (undoes git add)
 
						- git reset --soft HEAD~ undoes a git commit back to staging
 
						- git reset --hard HEAD~ undoes a git commit entirely
 
    				- use the commit number to revert to a specific commit
 
    				- use HEAD~2 to undo the last two commits
 
					
            
$ git log
  commit ecb76ad2f5b753c10f5f24094ea27f29f8c2d004
    Second commit
  commit 320a8f00a4a0de7c9b3f39851d3bc164d0769697
    First commit
$ git reset --hard HEAD~
or
$ git reset --hard 320a8f00a4a0de7c9b3f39851d3bc164d0769697
$ git log
  commit 320a8f00a4a0de7c9b3f39851d3bc164d0769697
    First commit
                
					
				
				
					Exercise: Experiment with git reset
					
								- Create some new files
 
								- Add the changes and then use git reset to un-add them
 
								- Add and commit some changes then use git reset to undo
 
								- How do the --soft and --hard flags change the behaviour?
 
								- Can you reset the whole project back to a specific commit?
 
					
            
$ git reset file2.txt
$ git reset --soft HEAD~
$ git reset --hard HEAD~2
$ git reset --hard 320a8f00a4a0de7c9b3f39851d3bc164d0769697
                
				
				
					Git revert
          Undo a commit but retain history
           
$ git log
  commit 28972f7572e9465cc6a0994ce5fcc31ba2d1afbb
  "Adding deploy button"
$ git revert HEAD~
  Revert "Adding deploy button"
  This reverts commit 28972f7572e9465cc6a0994ce5fcc31ba2d1afbb.
$ git log
  commit 78413bb6fec87d10f24ec5c62592795befdb66f7
  Reverts "Adding deploy button"
  commit 28972f7572e9465cc6a0994ce5fcc31ba2d1afbb
  "Adding deploy button"
          
				
				
					Exercise: using git revert
					
            - Make a change in a file
 
            - Add, commit, and push it
 
            - Now use git revert to roll back that change
 
            - Keep an eye on git log
 
            - What does the history look like when you've finished?
 
            - How is this different to git reset?
 
          
           
$ git revert HEAD~
  Revert "Adding deploy button"
  This reverts commit 28972f7572e9465cc6a0994ce5fcc31ba2d1afbb.
          
				
				
				
					Branches
					
            - One of git's most powerful features
 
            - Allow simultaneous work in different environments
 
            - Develop features
 
            - Only merge in new code when you're ready
 
          
				
				
					Git workflow: master branch only
					
					master is git's default main branch
				
				
					Git workflow: master branch and a hotfix branch
					
				
				
					Git workflow: development and release branches
					
				
				
					Branch commands
					
            - git branch displays the checked-out branches
 
            - git branch branchname creates a new branch
 
            - git checkout branchname switches to the new branch
 
            - git checkout -b combines the above commands to create a new branch and switch to it
 
            
          
$ git branch
*  master
$ git branch featurebranch
$ git branch
*  master
   featurebranch
$ git checkout featurebranch
$ git branch
* featurebranch
  master
          
				
    		
					Exercise: working with branches
					Let's make a new feature branch of the existing repository that you cloned.
          
$ git checkout -b featurebranch
Switched to a new branch 'featurebranch'
$ git branch
* featurebranch
  master
          
            - Create some more files and edit existing files
 
            - Add and commit your changes
 
            - The first time you push, you'll need to set up the remote for this branch like:
 
          
          
 $ git push --set-upstream origin featurebranch
          
				
					Merging branches
					
            - You've developed a whole new feature in the feature branch, and now it's time to merge it back into the master branch
 
            - We can merge branches on the command line
 
            - or use merge request in Gitlab (this is called 'pull request' in Github)
 
            - Merge requests are more appropriate for merging to production branches as they encourage code review and thoughtful deploys
 
          
				
				
					Exercise: merging branches in Gitlab
					
            - In Gitlab, create a new merge request to merge your feature branch into the master branch
 
            - Explore the request and check the changes you made
 
            - Accept the merge request
 
            - See the changes now appear in the main branch in Gitlab
 
            - Locally switch back to the master branch with git checkout and do a git pull to get up-to-date
 
          
          
$ git checkout master
  Switched to branch 'master'
  Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
    (use "git pull" to update your local branch)
$ git pull
  Updating 7a59581..4d4adb3
  Fast-forward
   file2.txt | 1 +
   1 file changed, 1 insertion(+)
    create mode 100644 file2.txt
          
          
				
				
					Exercise: merging branches on the command line
					
            - On the command line, ensure you're on the feature branch
 
            - Make some changes in the feature branch, add, commit, and push them
 
            - Switch back to the master branch, merge in the feature branch, and push back to the remote
 
            
$ git checkout master
$ git merge master featurebranch
$ git push
            
            - Note that we merge into the branch we're standing in
 
           
           
				
  
				
					Investigative tools
					
            - Sometimes we need to work out exactly what's going on in a repository
 
            - git log to see a history of commits
 
            - git reflog to see a history of both commits and amends
 
            - git blame filename to see who authored every line in a file
 
            - git log --graph to see the relationship of branches
 
           
            
$ git log --graph
* commit f91ed8cabfd053cde63f168087885bfdd0358419
|     Updated readme
|    
*   commit b8775a17e6fa9c9b6a9dd9f7b323a280a4db8faf
|\  Merge: 9544040 e99a3ac
| |     Merge branch 'master' of gitlab.example.com:myname/myproject
| |   
| * commit e99a3ac35a86c9bce4c8993ed8b6f1b7c8bf2a39
| |     Allow user login
| |   
* | commit 9544040efc0537d2f5a10975c0b779c3ccad0142
|/      Add remote users
|
          
          
				
				
					Exercise: Investigative tools
					
            - Try out the following tools:
 
            - git log to see a history of commits
 
            - git reflog to see a history of both commits and amends
 
            - git log --graph to see the relationship of branches
 
            - git blame filename to see who authored every line in a file
 
            
          
				
				
					Working with multiple stable branches
					
            - Alongside the main master branch, there can also be other stable branches
 
            - A common workflow is to develop features in a feature branch and then merge up through the environments
 
          
				
				
					Working with multiple stable branches
					
				
				
					Feature vs stable branches
				  	
							- Feature branches
 
              - can be considered private branches
 
                  - a place to experiment
 
                  - therefore often messy commit history
 
              
							- Stable branches
 
              - can be considered public branches
 
                  - need to think a bit more carefully about commit history
 
              
							
- Further reading: sandofsky.com/blog/git-workflow.html
 
				  	
				
				
					Caring for your
commit history
				
				
					Why do we need to worry about our commit history?
				  	
							- A well-maintained commit history will allow you to:
 
              
							- track when features were introduced
 
							- discover when bugs were introduced
 
							- provides some amount of documentation
 
				  	
							- A good commit history tells a story
 
            
				
				
					Commit message guidelines
				  	
							- Use one line to describe what the commit does
 
							- Examples of good commit messages:
 
              
  							- Allow users to sign in remotely
 
  							- Fixed bug #123
 
  							- Added postcode field to address table
 
	  			  	
							- Examples of bad commit messages:
 
              
  							- Commit4
 
  							- Typo
 
  							- dfkasdjefskjh
 
	  			  	
            
				
				
					Commit history choices: Rebasing
				  	
							- You've made a feature branch, and done some work on it
 
							- but while you've been working on it, your colleagues have made some changes to master
 
							- if you do a git merge all the master commits will go on top of your feature commits
 
							- So instead we do a git rebase to apply the commits underneath your feature commits
 
              
							- Let's demonstrate the difference with a diagram
 
				  	
				
				
				
					Commit history choices:
Merging with fast-forwarding
				  	
							- If no changes have occured on the master branch while feature development was underway
 
							- git will try to merge branches with fast-forward
 
							- All commits from the feature branch are visible in the master branch
 
							- This can be useful, or can be clutter in the version history
 
              - We can use --no-ff to submit a single commit for the merge
 
              
							- Let's visualise the difference
 
				  	
				
				
				
					Editing the commit history
				  	
							- In order to tell a good story with your commit history, you will probably need to edit your commit history at times
 
							- git commit --amend lets you amend your most recent commit
 
							- git rebase --interactive for more complex history rewrites
 
							- git push --force branchname to push your new historys
 
							- NB NEVER rewrite your commit history after you've 'gone public' with the branch (ie, pushed to a shared repository).
 
            
        
				
					Interactive rebase
				  	
							- git rebase --interactive will drop you into a text editor where we can specify all the things we want to change
 
							- Commands:
 
							  - pick = use commit
 
							  - reword = use commit, but edit the commit message 
 
							  - edit = use commit, but stop for amending
 
							  - squash = use commit, but meld into previous commit
 
							  - fixup = like "squash", but discard this commit's log message
 
							  - exec = run command (the rest of the line) using shell
 
              
				  	
          
				
				
					Interactive rebase
				  	
             
$ git rebase -i HEAD~3
pick 6c169da Fixed bug #234
pick 78413bb Typo in user prefs 
pick 2bc4f9b Allow users to update their preferences
# Rebase 28972f7..2bc4f9b onto :w28972f7
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
# Note that empty commits are commented out
          
          
				
				
					Rewrite a commit message
				  	
             
$ git rebase -i HEAD~3
reword 6c169da Fixed bug #234
pick 78413bb Typo in user prefs 
pick 2bc4f9b Allow users to update their preferences
            
             
Fixed bug #234: do not allow remote access to db
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
            
             
$ git log
commit 6c169da
  Fixed bug #234: do not allow remote access to db
          
          
				
				
					Squashing commits together
				  	
             
$ git rebase -i HEAD~3
pick 6c169da Fixed bug #234: do not allow remote access to db
squash 78413bb Typo in user prefs 
pick 2bc4f9b Allow users to update their preferences
            
             
Rebasing
# This is a combination of 2 commits.
# The first commit's message is:
Fixed bug #234: do not allow remote access to db
# This is the 2nd commit message:
Typo in user prefs
            
             
$ git log
commit 9107a08
    Fixed bug #234: do not allow remote access to db
    Typo in user prefs
commit 2bc4f9b
    Allow users to update their preferences
          
          
				
				
					Final Exercise: Rewrite history
				  	
				  	
							- Try out git rebase --interactive
 
							- Rewrite a historic commit message
 
							- Squash some commits together
 
							- Edit a previous commit
 
							- Don't panic!
 
          
				
				
					Summary
					
							- Version control
 
							- Git concepts
 
							- Using git locally
 
							- Using git with a remote
 
							- Undoing mistakes
 
							- Branches
 
							- Caring for your commit history