Skip to content

Instantly share code, notes, and snippets.

@rafaellehmkuhl
Last active November 16, 2017 02:50
Show Gist options
  • Save rafaellehmkuhl/80cb2e731e400f862ebe27ab9c04b3c4 to your computer and use it in GitHub Desktop.
Save rafaellehmkuhl/80cb2e731e400f862ebe27ab9c04b3c4 to your computer and use it in GitHub Desktop.
My standard git workflow

My Standard Git Workflow

Initial workflow (done once)

Forking

I start my workflow Forking the Main Repository, this is, the repository which I want to contribute to. The repository's URL should be something like https://github.com/author_username/repository_name

On the topright you will se a button like the one above. Click it and you will have the repository forked.

Cloning

When the main repository is forked, I go to my fork's repository and Clone it. The fork's repository URL should be something like: https://github.com/my_username/repository_name

To Clone the repository you need first to copy the HTTPS repository URL. You can do it using the Clone button, like int the image below.

Then, on your computer, you should open a folder where the Git files for that repository will be stored. Once inside the folder, open a terminal there, and use the following command:

git clone https://github.com/my_username/repository_name.git

Git will now download all the files and the git history for that repository.

Setting remote upstream

Once you have the repository cloned, you can enter it

cd repository_name

You are now inside the git repository, and can use the entire set of git commands. The first thing we will do is add the main repository as a remote upstream. We do that so when we are done developing our features we can send the feature branch as a Pull Request to the main repository, contributing to it.

To add the main repository as a remote use the following comand:

git remote add upstream https://github.com/author_username/repository_name.git

This command will add a new remote called upstream with https://github.com/author_username/repository_name.git as it's adress.

Main workflow

Branching

Once you've done the initial steps, you're ready to contribute to the main repository.

There's a golden rule largely accepted when using git: never develop on the master branch. This is because the master branch should always be deployable, and this will not be the case if you use it to develop. You should think of your master branch as a secret place which just accept features that fully work. We know that this will not always be the case, and that if you're on a big project, there's a high chance that bugs will pass to the master branch sometime, but this should be minimized as possible. That's why when we are developing something, we do that on a separate branch.

You will create a new branch for every new feature, bugfix or enchancement that you develop. Every one of those should have it's own branch, so you have separate "packages" of changes, where everything in that package is related to the main ideia of that branch. You will see that doing so will turn things mush easier in the future.

To create a new branch, first we need to go the the master branch, so this become a branch of master:

git checkout master

Next, to create the branch, simple enter the following commands:

 git branch feature_branch
 git checkout feature_branch

The first command will create a branch called feature_branch, while the following command will enter this branch. Usually people don't use those two command, but instead, use just the following one:

 git checkout -b feature_branch

This command will create feature_branch and automatically enter it.

The first thing I always do when creating a new branch is setting it's upstream branch, with the following command:

 git --set-upstream origin feature_branch

When you do this you are basically saying that, whenever you push this branch (feature_branch), you want it to be pushed to the remote called origin (this is the remote pointing to your forked repository). In this way you can develop your branch in your fork and, when done, you can Pull Request it to the main repository.

Commiting

Once your branch is setup you can start commiting.

A commit is a group of changes in the code that make sense to be together. Everytime you change something in the code you should make a commit with it. If you do so, anyone can look at your code and see where you changed every part of the code, and that includes you. If you make some change and brake the code, you can see when it broke and correct it.

To make a commit, first you change what you need in the code and save the files that changed. Then you add those files to the stage area and finally you commit it. This is done with the following commands:

git add file_name
git commit -s

Rebasing

Now you've created your branch, and maybe you commited changes to it or not, but let's say that some time passed since you created that branch. On this meantime maybe other developers pushed changes to master (the main repository, upstream, master), and maybe some of those changes changed some code that is important to your branch, that is, your branch is now incompatible with the new master.

What you need to do is sync your local master to the upstream (main repository) master, and them sync your local feature_branch to your local master (which is already synced). This process of syncing one branch based on another is called rebasing.

To rebase your local master first you need to checkout to the master branch

git checkout master

Then you will use the following command:

git pull --rebase upstream master

Usually the command pull would fetch the changes made on some branch (in this case upstream's master) and then merge then to the current branch where we are (local's master), but we've put a --rebase flag there, which will change the merge for a rebase. The motive for rebasing instead of merging is that we want to keep a clean working tree. If we merged (using just "git pull") we would be creating a new local commit with all the changes made on upstream's master concateneted. This is bad because you would end up with a messy working tree.

So in the end this command will fetch the changes made on upstream's master and rebase them into local's master, making our local master a exactly copy of upstream's master.

This command should never give you conflicts because you local master should never have changes that are not in upstream's master.

Now that your local master is synced, you will go to your feature_branch and rebase it with respect to master:

git checkout feature_branch
git rebase master

This process become very intuitive in the gif below.

Notice that on your branch use to be based on an old commit (which was the last one when you created your branch), and when you use "git rebase" your branch is now based on the last commit from master. This command may give you conflicts, when someone pushed changes to master that turned your branch incompatible, but the advantage of doing a git rebase on your branch every once in a while is that you can simple solve your conflicts in small pieces, instead of having to resolve a big and messy conflict with a lot of changes in the end.

Solving conflicts

If any conflict raised now is the time to solve it. To solve your conflict you can:

  1. Take a look on the conflict message, which indicates which files have conflicts
  2. Open that file, solve the conflict and save it
  3. Git add the file which was in conflict
  4. Continue your rebase

To add the file with conflict, use:

git add file_with_conflict

And then, to continue the rebase, simply use:

git rebase --continue

Your feature_branch is now synced with master and you are free to make new changes to it, without the worry of coding on top of deprecated code.

Pushing your branch and Pull Requesting

When you finish making changes to your branch you can push it to you remote fork. To do that use:

git push

If you had already pushed that branch to remote, you may receive a conflict when pushing again. This is because you rebased your branch, and when you do this you change the commit history, turning you remote branch history different from your local one. To solve this you can simply force the push using:

git push --force

Now you have your branch on your forked repository, and if you are confident that it is finished you can make a Pull Request to the main repository.

To do that, go to your forked repository and click on the Pull Request button.

Doing so will open the Pull Request page, where you can write a message to the maintainer of the project indicating what you did. Once wrote, click the "Send Pull Request" button.

If the maintainer request changes, simply make the changes, commit them and do a "git push" again, till your Pull Request is accepted and merged.

Finishing a cicle (a.k.a rebasing and pushing your master)

Once your Pull Request is accepted, simply go to your local master, pull and rebase the changes from upstream's master and push them to your origin (forked repository) master, with the following commands:

git checkout master
git pull --rebase upstream master
git push origin master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment