<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Lecture 3
Step1:  Once you're in your playground repo, you can look at all the branches and print out a lot of information to the screen.
Step2:  All of these branches are nothing but commit-streams in disguise, as can be seen above. It's a very simple model that leads to a lot of interesting version control patterns.
Since branches are so light-weight, the recommended way of working on software using git is to create a new branch for each new feature you add, test it out, and if good, merge it into master. Then you deploy the software from master. We have been using branches under the hood. Let's now lift the hood.
branch
Branches can also be created manually, and they are a useful way of organizing unfinished changes.
The branch command has two forms. The first
Step3:  See what branches we have created.
Step4:  Notice that you have created the mybranch1 branch but you're still on the master branch.
Jump onto the mybranch1 branch...
Step5:  Notice that it is bootstrapped off the master branch and has the same files.  You can check that with the ls command.
Step6:  Note
Step7:  Alright, so we're on our new branch but we haven't added or modified anything yet; there's nothing to commit.
Adding a file on a new branch
Let's add a new file.  Note that this file gets added on this branch only!  Notice that I'm still using the echo command.  Once again, this is only because jupyter can't work with text editors.  If I were you, I'd use vim.
Step8:  We add the file to the index, and then commit the files to the local repository on the mybranch1 branch.
Step9:  At this point, we have committed a new file (books.md) to our new branch in our local repo.  Our remote repo is still not aware of this new file (or branch).  In fact, our master branch is still not really aware of this file.
Note
Step10:  Fail! Why? Because Git didn't know what to push to on origin (the name of our remote repo) and didn't want to assume we wanted to call the branch mybranch1 on the remote. We need to tell that to Git explicitly (just like it tells us to).
Step11:  Aha, now we have both a remote and a local for mybranch1.  We can use the convenient arguments to branch in order to see the details of all the branches.
Step12:  We make sure we are back on master
Step13:  What have we done?
We created a new local branch, created a file on it, created that same branch on our remote repo, and pushed all the changes.  Finally, we went back to our master branch to continue work there.
Short-lived branches
Now we'll look into option 2 above.  Suppose we want to add a feature to our repo.  We'll create a new branch to work on that feature, but we don't want this branch to be long-lived.  Here's how we can accomplish that.  
We'll go a little faster this time since you've seen all these commands before.  Even though we're going a little faster this time, make sure you understand what you're doing!  Don't just copy and paste!!
Step14:  At this point, we've committed our new feature to our feature branch in our local repo.  Presumably it's all tested and everything is working nicely.  We'd like to merge it into our master branch now.  First, we'll switch to the master branch.
Step15:  The master branch doesn't have any idea about our new feature yet!  We should merge the feature branch into the master branch.
Step16:  Now our master branch is up to date with our feature branch.  We can now delete our feature branch since it is no longer relevant.
Step17:  Finally, let's push the changes to our remote repo.
<ASSISTANT_TASK:>
Python Code:
%%bash
cd /tmp
rm -rf playground #remove if it exists
git clone https://github.com/dsondak/playground.git
Explanation: Lecture 3: Branches with Git
In Lecture 2, you worked with the playground repository.  You learned how to navigate the repository from the Git point of view, make changes to the repo, and work with the remote repo.
One very important topic in Git involves the concept of the branch.  You will work extensively with branches in any real project.  In fact, branches are central to the Git workflow.  In this portion of the lecture, we will discuss branches with Git.
For more details on branches in Git see Chapter 3 of the Git Book: Git Branching - Branches in a Nutshell.
Branching
As you might have noticed by now, everything in Git is a branch. We have branches on remote (upstream) repositories, copies of remote branches in our local repository, and branches on local repositories which (so far) track remote branches (or more precisely local copies of remote repositories).
Begin today's lecture by entering your playground repository from last lecture.  Note that the following cell is not necessary for you.  I have to re-clone the repo since I'm in a new notebook.  You should just keep working like you were before.
End of explanation
%%bash
cd /tmp/playground
git branch -avv
Explanation: Once you're in your playground repo, you can look at all the branches and print out a lot of information to the screen.
End of explanation
%%bash
cd /tmp/playground
git branch mybranch1
Explanation: All of these branches are nothing but commit-streams in disguise, as can be seen above. It's a very simple model that leads to a lot of interesting version control patterns.
Since branches are so light-weight, the recommended way of working on software using git is to create a new branch for each new feature you add, test it out, and if good, merge it into master. Then you deploy the software from master. We have been using branches under the hood. Let's now lift the hood.
branch
Branches can also be created manually, and they are a useful way of organizing unfinished changes.
The branch command has two forms. The first:
git branch
simply lists all of the branches in your local repository. If you run it without having created any branches, it will list only one, called master. This is the default branch. You have also seen the use of git branch -avv to show all branches (even remote ones).
The other form of the branch command creates a branch with a given name:
It's important to note that this new branch is not active. If you make changes, those changes will still apply to the master branch, not my-new-branch. That is, after executing the git branch my-new-branch command you're still on the master branch and not the my-new-branch branch.  To change this, you need the next command.
checkout
Checkout switches the active branch. Since branches can have different changes, checkout may make the working directory look very different. For instance, if you have added new files to one branch, and then check another branch out, those files will no longer show up in the directory. They are still stored in the .git folder, but since they only exist in the other branch, they cannot be accessed until you check out the original branch.
You can combine creating a new branch and checking it out with the shortcut:
Ok so lets try this out on the playground repository.
End of explanation
%%bash
cd /tmp/playground
git branch 
Explanation: See what branches we have created.
End of explanation
%%bash
cd /tmp/playground
git checkout mybranch1
git branch
Explanation: Notice that you have created the mybranch1 branch but you're still on the master branch.
Jump onto the mybranch1 branch...
End of explanation
%%bash
cd /tmp/playground
ls
Explanation: Notice that it is bootstrapped off the master branch and has the same files.  You can check that with the ls command.
End of explanation
%%bash
cd /tmp/playground
git status
Explanation: Note: You could have created this branch and switched to it all in one go by using git checkout -b mybranch1.
Now let's check the status of our repo.
End of explanation
%%bash
cd /tmp/playground
echo '# Things I wish G.R.R. Martin would say:  Finally updating A Song of Ice and Fire.' > books.md
git status
Explanation: Alright, so we're on our new branch but we haven't added or modified anything yet; there's nothing to commit.
Adding a file on a new branch
Let's add a new file.  Note that this file gets added on this branch only!  Notice that I'm still using the echo command.  Once again, this is only because jupyter can't work with text editors.  If I were you, I'd use vim.
End of explanation
%%bash
cd /tmp/playground
git add .
git status
%%bash
cd /tmp/playground
git commit -m "Added another test file to demonstrate git features" -a
git status
Explanation: We add the file to the index, and then commit the files to the local repository on the mybranch1 branch.
End of explanation
%%bash
cd /tmp/playground
git push
Explanation: At this point, we have committed a new file (books.md) to our new branch in our local repo.  Our remote repo is still not aware of this new file (or branch).  In fact, our master branch is still not really aware of this file.
Note: There are really two options at this point:
1. Push the current branch to our upstream repo.  This would correspond to a "long-lived" branch.  You may want to do this if you have a version of your code that you are maintaining.
2. Merge the new branch into the local master branch.  This will happen much more frequently than the first option.  You'll be creating branches all the time for little bug fixes and features.  You don't necessary want such branches to be "long-lived".  Once your feature is ready, you'll merge the feature branch into the master branch, stage, commit, and push (all on master).  Then you'll delete the "short-lived" feature branch.
We'll continue with the first option for now and discuss the other option later.
Long-lived branches
Ok, we have committed. Lets try to push!
End of explanation
%%bash
cd /tmp/playground
git push --set-upstream origin mybranch1
Explanation: Fail! Why? Because Git didn't know what to push to on origin (the name of our remote repo) and didn't want to assume we wanted to call the branch mybranch1 on the remote. We need to tell that to Git explicitly (just like it tells us to).
End of explanation
%%bash
cd /tmp/playground
git branch -avv
Explanation: Aha, now we have both a remote and a local for mybranch1.  We can use the convenient arguments to branch in order to see the details of all the branches.
End of explanation
%%bash
cd /tmp/playground
git checkout master
Explanation: We make sure we are back on master
End of explanation
%%bash
cd /tmp/playground
git checkout -b feature-branch
%%bash
cd /tmp/playground
git branch
%%bash
cd /tmp/playground
echo '# The collected works of G.R.R. Martin.' > feature.txt
%%bash
cd /tmp/playground
git status
%%bash
cd /tmp/playground
git add feature.txt
git commit -m 'George finished his books!'
Explanation: What have we done?
We created a new local branch, created a file on it, created that same branch on our remote repo, and pushed all the changes.  Finally, we went back to our master branch to continue work there.
Short-lived branches
Now we'll look into option 2 above.  Suppose we want to add a feature to our repo.  We'll create a new branch to work on that feature, but we don't want this branch to be long-lived.  Here's how we can accomplish that.  
We'll go a little faster this time since you've seen all these commands before.  Even though we're going a little faster this time, make sure you understand what you're doing!  Don't just copy and paste!!
End of explanation
%%bash
cd /tmp/playground
git checkout master
ls
Explanation: At this point, we've committed our new feature to our feature branch in our local repo.  Presumably it's all tested and everything is working nicely.  We'd like to merge it into our master branch now.  First, we'll switch to the master branch.
End of explanation
%%bash
cd /tmp/playground
git merge feature-branch
%%bash
cd /tmp/playground
git status
ls
Explanation: The master branch doesn't have any idea about our new feature yet!  We should merge the feature branch into the master branch.
End of explanation
%%bash
cd /tmp/playground
git branch -d feature-branch
Explanation: Now our master branch is up to date with our feature branch.  We can now delete our feature branch since it is no longer relevant.
End of explanation
%%bash
cd /tmp/playground
git push
Explanation: Finally, let's push the changes to our remote repo.
End of explanation
<END_TASK>