In Puppet and Git 101, we looked at how to add our existing puppet code to our repo. We’re going to take a quick look at how to create a branch, add some code, commit it, and push it to our repo.
Create a Branch
For lack of something significant to do right now, we’ll add a notify command to the node definition for puppet.nelson.va. To do so, we will checkout a new branch called, appropriately, notify. You can call your branches whatever you want, I suggest you simply be consistent in your naming scheme. At work, I use a combination of a ticket number and a one or two word description of the feature, separated by hyphens. Normally our branch is going to be short lived and only exist locally (we’re going to make an exception to that for demo purposes), so it would be a moot, but it’s still a good habit to be in.
[root@puppet puppet]# git branch * master [root@puppet puppet]# git checkout -b notify Switched to a new branch 'notify' [root@puppet puppet]# git branch master * notify
Add a notify statement to the manifests/site.pp file as below:
[root@puppet puppet]# cat manifests/site.pp node 'puppet.nelson.va' { include ::base notify { "Generated from our notify branch": } }
When we check the status now we will see that a file has changed, but it is not added to the commit. A commit would fail. We can add it to be tracked, or we can add it and commit in a single command.
[root@puppet puppet]# git status # On branch notify # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: manifests/site.pp # no changes added to commit (use "git add" and/or "git commit -a") [root@puppet puppet]# git commit -a -m 'Adds notify to puppet master node definition' [notify 7899e2d] Adds notify to puppet master node definition 1 files changed, 1 insertions(+), 0 deletions(-)
Note that I used the present tense in my commit message. This is a very religious argument, so I’ll just stop there 🙂
Change branches
Now that the change is committed, we can change branches very quickly and see the differences in the site manifest. Let’s check that out quickly.
[root@puppet puppet]# cat manifests/site.pp node 'puppet.nelson.va' { include ::base notify { "Generated from our notify branch": } } [root@puppet puppet]# git checkout master Switched to branch 'master' [root@puppet puppet]# cat manifests/site.pp node 'puppet.nelson.va' { include ::base } [root@puppet puppet]# git checkout notify Switched to branch 'notify' [root@puppet puppet]# cat manifests/site.pp node 'puppet.nelson.va' { include ::base notify { "Generated from our notify branch": } }
Swanky.
Pushing a branch
You’ve committed your branch, but it doesn’t show up on Github (on the project page, there’s a branch pulldown right above the file listing). If someone else wants to see your branch, they need to grab it from the puppet master. That’s probably okay…unless your master blows up and you lose the local repo. We need to push the branch to origin so it’s available elsewhere. We use the format git push <remote> <branch>.
[root@puppet puppet]# git push origin notify Password: Counting objects: 7, done. Compressing objects: 100% (3/3), done. Writing objects: 100% (4/4), 409 bytes, done. Total 4 (delta 1), reused 0 (delta 0) To https://rnelson0@github.com/rnelson0/puppet-tutorial.git * [new branch] notify -> notify
Once the branch is available on github, others can check it out from there and you have some level of resiliency against data loss. Next, we need to…
Merge the branch
Now that our new branch works, for all sufficiently low values of work, we want to merge the work into our master branch. You do this by checking out the master branch, then merging the notify branch into it. Don’t forget to push it to origin!
[root@puppet puppet]# git checkout master Switched to branch 'master' [root@puppet puppet]# git merge notify Updating bc1e27b..7899e2d Fast-forward manifests/site.pp | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) [root@puppet puppet]# git push origin master Password: Total 0 (delta 0), reused 0 (delta 0) To https://rnelson0@github.com/rnelson0/puppet-tutorial.git bc1e27b..7899e2d master -> master
Multiple Branches
What we did above was pretty simple, one branch for one feature and then we merged it back into master. In the future, we may work on concurrent branches at once. You might be working on a manifest definition for the puppet master and a colleague may be working on server01. Or you’re fixing two different problems with the same node. Git allows you to create multiple branches, make changes to different code (sometimes in the same file) and merge the branches independently. If you do make changes to the same code as someone else, there are methods to address this, too.
We’re not going to get into concurrent development, as this is a little beyond our focus of Puppet, but you should be aware of the functionality available to you, should you need it. Checkout this git branching model tutorial for more details.
Deleting a Branch
Our notify branch isn’t something we need to keep around anymore, now that the changes are merged into master. Delete it locally with git branch -d <branch>.
[root@puppet puppet]# git branch -d notify Deleted branch notify (was 7899e2d).
Of course, it’s still available on github. If you need it again, you can pull it down with git checkout notify, as can anyone else who has cloned it. That might be okay for some feature branches – perhaps you have a perpetual development branch, or a v1.1 or v2.0 branch for a new version – but not for such a simple branch like this. We can delete it with either git push origin -d <branch> (git 1.7.0+) or git push origin :<branch> (git 1.5.0+). I’ll use the latter, as I like the brevity.
[root@puppet puppet]# git push origin :notify Password: To https://rnelson0@github.com/rnelson0/puppet-tutorial.git - [deleted] notify
Refresh your Github page and you’ll see just one branch, master. You could, of course, also have deleted the branch on Github itself, but that’s no fun. Be aware that you cannot undelete branches via Github (except when done via a pull request). Because it’s a distributed VCS, you could always retrieve the branch from another copy of the repo. If you’re careful when deleting branches, you won’t have to worry about such issues.
Revert to v0.1
We’ve merged the notify branch into the master branch and then deleted it. What if we want to go back? There are a few ways to do so, which relies on (to me) archaic syntax involving checksums. Does git checkout c2e7af2b51
seem user friendly? Thankfully, we made a tag for v0.1 earlier. We can go back to that version very quickly, the same way we did before, and see the change in place by looking at the site manifest.
[root@puppet puppet]# cat manifests/site.pp node 'puppet.nelson.va' { include ::base notify { "Generated from our notify branch": } } [root@puppet puppet]# git checkout tags/v0.1 Note: checking out 'tags/v0.1'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b new_branch_name HEAD is now at bc1e27b... Initial puppet config [root@puppet puppet]# cat manifests/site.pp node 'puppet.nelson.va' { include ::base }
As noted earlier, you are now in a detached HEAD state which means no changes. You’ll have to resort to one of the other methods if you need to make changes. Checkout master again to return to a normal status.
Environments
We didn’t do a whole lot of meaningful Puppet work today as we focused on git workflows. The next thing we need to do is set up are some environments. Each puppet agent requests a catalog from an environment. By default we only have a production environment, but we can define additional environments and give different agents different catalogs. Each git branch will be a different environment, and we’ll merge the features back in to master when they’ve tested out – exactly what we did today. We’ll use what we learned today to set up environments in the next piece.