Code Review Git Workflow
Tags: python, jenkins, automation, git
Published: 2020-01-24 04:26:33


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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. Jenkins can be used to automatically trigger builds for projects when new code is pushed to our Bitbucket repos, or on a schedule, 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!




<img src="https://confluence.atlassian.com/bitbucket/files/304578655/945541427/1/1518542414564/review_process.png" />

# git workflow and Jenkins project structure



#### Let's avoid merge conflicts! :stuck_out_tongue_winking_eye:
   

1. Make a new folder locally where you will do your code review from. Leave it empty for now. 

2. 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
    ```

3. Commit and push the following minimal files to master: .gitignore, 
\_\_init\_\_.py

    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 
    over.

4. 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>
    ```
    or
    * 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
    ```

5. 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.

    Windows commands:
    ```
    $ 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
    ```
6. 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
    ```
7. Handle merge conflicts before opening your PR. The below commands will pull the latest changes from remote master, and merge into your feature branch locally. I have set VSCode as my git merge.tool, core.editor, diff.tool, etc. so I don't have to deal with memorizing Vim commands. I highly recommend doing this to keep things simple.
    ```
        $ git checkout master	
        $ git pull
          (...updates get pulled down...) ---+++++
        $ git checkout <new_branch_name>
        $ git merge master
          (resolve merge conflicts in VSCode, 
           enter merge commit message, push/sync)
    ```
8. Merge conflicts have been resolved, and your remote feature branch contains the updates. Now you can be certain that once you create a pull request, there will be no merge conflicts. Open a pull request, and add reviewers.
9. Once review is complete, click "Merge" on Bitbucket
10. 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. PRO-TIP: DON'T CREATE A TAG WITH THE SAME NAME AS THE FEATURE BRANCH NAME.
    ````
    $ 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.
11. 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! :grin: 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!