Git is currently the most widely used version control system (VCS) in the world, mainly due to GitHub. Version control systems record changes to a file or set of files over time so that you can recall specific versions later. Git is a distributed form of version control, where each system, not just a central location, has a full repository.
Projects hosted on GitHub, or your own personal remote repositories, are fully mirrored when they are cloned. This means that when you pull down a repository, you get all of the files contained in it, you can make changes and commit them back to your own fork of the project, clone different versions, or just clone and compile. You can even push your changes into staging for the main project.
Git is built into macOS, so we won't have to download anything. I'll be covering the bare basics in this article, just enough to get us off the ground modifying some code and maintaining our own local repositories. By using Git, we will be able to clone popular open-source hacking tools, compile them, and even make changes or push bug fixes!
The git clone command is what we'll be using to pull source off of GitHub. It's probably the most common command you'll use as a pentester, unless you also do development on the side. In order to use this command, simply find a repo (I selected theHarvester) and execute the following command, swapping out the repo I chose with whatever you chose.
- git clone https://github.com/laramies/theHarvester
There we have it. I now have a copy of theHarvester for my own use. However, I am missing a required dependency—the Python requests library. Since we are dealing with source code when cloning from GitHub, it's common that dependencies will not be met. If we were pulling this from a package manager such as Homebrew, the package would include the dependencies. In this case, I simply need to install pip (a package manager for Python libraries) and pull down the appropriate dependencies.
The git init command allows us to initialize a directory as a Git repository, allowing us local version control of our projects in development. I created a simple project and initialized the directory into a local repo with:
- git init
When you initialize a directory, Git will create a .git folder which tracks changes to your project. At the moment, Git will not track any of the files in my projects folder because I haven't added them to the track list yet.
Now that I have an initialized folder, it's time to add the files for tracking. I'll do this with:
- git add *
We can see that Git is tracking my files. When I make changes to the files, Git tracks those changes. When I'm happy with the code, I can commit the changes (see the next step). In the meantime, Git keeps track of what I'm working on.
The lifecycle of a Git file starts with the addition of the file. It then tracks changes to that file until the file is committed. Once the file has been committed, it returns to an unmodified state. A commit is essentially saying you are happy with code in the file. The cycle then starts again at the unmodified state.
Once I'm satisfied with the state that my files are in. I will commit the changes using the command:
- git commit -a -m 'changed some core UI components'
The git commit part is telling Git that the modifications made to the files are ready to go. The -a flag tells Git to commit all currently tracked files, while the -m flag is the message to include with these changes.
Sometimes we leave projects for a long time, and other times it's just difficult to keep track of what's happening. Luckily, we can find out the status of the repository with:
- git status
I've been using the command through out all stages of my repository to show what Git is doing behind the scenes. This command shows me untracked files, files that have changed but have not committed, and my working branch.
Branches allow you to add or test new features without making changes to the stable code base. For example, my hackThePlanet.py has been committed and it's currently stable, but I want to add some new experimental features without breaking anything in the stable version. In that case, I would use the command:
- git branch experimental
This will create a new branch of the project. Next, I switch over to the experimental branch with:
- git checkout experimental
I could have also done this with the command:
- git checkout -b experimental
This command checks out a new branch that is specified with the -b flag.
Now that I have a new branch, I'll add in my experimental features, get everything working, and commit the changes to the branch. If I were working with a team, it's possible there would be multiple branches of the stable version—one branch for new UI elements, another branch with bug fixes, and maybe another branch where there is some new functionality being added. Of those branches, more people might branch them to work on specific pieces.
Since everything went so well with our changes, it's time to merge my branches back together. First, I checkout the master branch using:
- git checkout master
Next, I will merge my master with my experimental branch using the command:
- git merge experimental
Now the master branch contains the new, no longer experimental code changes. I can always go back and check out the experimental branch and continue adding new features, or create new branches.
This is a very basic intro to working with Git. There are many powerful features that I did not cover here. I only touched on what was necessary to work with your own local repositories on your machine. Git is capable of so much more, especially when used in conjunction with GitHub.
While some of you may not ever use these features, it's important to know they are there. There are times in pen-testing where you will have to modify a PoC (proof of concept) or get a piece of code working on your system. If you find yourself doing this kind of work, these basics will help to keep your workflow organized. As with most commands, git is extremely well-documented. Commands like git branch --help will open man pages specific to the command. I suggest reading through these.
Coming up, we'll be looking at another toolbox working with RVM, as well as finalizing our setup.