I recently became the git guru at my job because there has been a huge push to automate anything and everything. The automation work done in my department requires python scripts to run at a consistent time every day. We centralize our automation efforts using Jenkins. Jenkins is an open source automation server, for continuous delivery/continuous integration. At my company, ours is set up to automatically trigger builds for our projects when new code is pushed to our Bitbucket repos, thereby contributing to the continuous integration cycle. Disclaimer: There are many other ways to use Jenkins, but that is outside the scope of this article. This workflow is specific to me, my team, Bitbucket code review, and a python project structure. It will discuss branching, tagging, merging, and deleting. However, the commands are generic enough so I figured this article could help train new team members, and anyone else who is interested in a similar workflow. On to the content!
Make a new folder locally where you will do your code review from. Leave it empty for now.
Make a new repo on Bitbucket, and run the command from the "My code is ready to be pushed" section in your new directory from (1):
$ cd existing-project $ git init $ git add --all $ git commit -m "initial commit" $ git remote add origin https://your.domain.com/your_project.git $ git push -u origin master
Commit and push the following minimal files to master: .gitignore,
DO NOT commit your main python script. If you commit your entire
python script at this stage, the reviewers will not be able to
comment on anything. They will only be able to comment within + or -
10 lines of a given change. If you pushed too many files to master at
this stage, it would be quickest to just delete the repo and start
The next step is to make a new branch. We need a new branch to fully review a pull request. Once your master branch is made, there are two ways I would go about making another branch from master:
- Remotely first (on Bitbucket via the browser), then locally. If you do this, make a new branch on Bitbucket in the browser, and then enter these commands.
$ git fetch $ git checkout <new_branch_name>
- Locally first (via gitbash, cmd, iTerm etc.), then remotely. If you do this, you don't have to do anything in the browser.
$ git checkout -b <new_branch_name> $ git push -u origin <new_branch_name>
Take your pick. If you want to confirm which branch you are on, simply run:
$ git branch
Once this new branch is obtained locally, create a python 3.x virtual environment (venv) - whichever python version your Jenkins is setup to run, and update the .gitignore and requirements.txt and/or setup.py, etc. as needed. We really only need requirements.txt technically. Add Jenkinsfile, .gitignore, __init__.py, etc. It only matters if the venv is activated for this part.
$ venv\Scripts\activate $ (venv) pip install package1 pagacke2 package3 $ (venv) pip freeze > requirements.txt
Linux & macOS commands:
$ source venv/bin/activate $ (venv) pip install package1 package2 package3 $ (venv) pip freeze > requirements.txt
Do your project editing here. Commit and push to your branch:
$ git add . $ git commit -m "feat: blah blah blah" $ git push -u origin <new_branch_name>
If your pull request is marked as "needs work" during the code review, just keep editing here and repeating the above commands.
You want your project to look like this in the end:
Client_Project/ |____ .git/ |____ venv/ |____ __init__.p |____ README.md |____ Jenkinsfile |____ .gitignore |____ requirements.txt |____ script_name.py
When your script is ready for Jenkins, create a pull request on Bitbucket. Again, if your pull request is marked as "needs work", make the requested changes, and use these commands to update the pull request:
$ git add . $ git commit -m "refactor: blah blah blah" $ git push -u origin <new_branch_name>
Once review is complete, and any merge conflicts have been handled, click "Merge" on Bitbucket
Tag your feature branch on master (annotated method preferred as there is more detail for team projects). Instructions are here: https://git-scm.com/book/en/v2/Git-Basics-Tagging
$ git tag -a <tag_name> -m "tag message" $ git push origin <tag name>
Think of this step as making a respawn point in a video game. You're naming a specific commit something special so you can git checkout the tag name if you need to later.
Once tagged, delete the old branch if everything is working as expected, and you have had several successful Jenkins builds. You can't delete a branch that you're on, so switch back to master:
$ git checkout master $ git branch
Delete locally first:
$ git branch -D <new_branch_name>
Delete remotely next:
$ git push origin --delete <new_branch_name>
That's all folks! That's the tweet! 😁 I hope this was helpful for you because it was definitely a learning process for me. If you have any feedback, I'm always open to improving. Anyway, happy coding!