Skip to content

Instantly share code, notes, and snippets.

@KoopaKing
Last active July 17, 2020 05:09
Show Gist options
  • Save KoopaKing/e10ec2fa16a69880bf2c8bc916193a11 to your computer and use it in GitHub Desktop.
Save KoopaKing/e10ec2fa16a69880bf2c8bc916193a11 to your computer and use it in GitHub Desktop.

Git setup for success. In this example I'll be solving fictional issue #420.

Verify Setup

This assumes you have two remotes, origin that you own and upstream for the master repository.

You can verify this initial setup with this command:

user@host:~$ git remote -v
origin	https://github.com/KoopaKing/step23-2020.git (fetch)
origin	https://github.com/KoopaKing/step23-2020.git (push)
upstream	https://github.com/googleinterns/step23-2020.git (fetch)
upstream	https://github.com/googleinterns/step23-2020.git (push)

Start a Fresh Branch

When you start working on an issue, the first thing you want to do is branch from a fresh copy of upstream master. While you can always pull and rebase later (and this workflow will do that), starting from an up to date master means we will have the lowest chance of having conflicts to resolve before merging.

user@host:~$ git checkout master
Switched to branch 'master'
user@host:~$ git pull upstream master
From https://github.com/googleinterns/step23-2020
 * branch            master     -> FETCH_HEAD
Already up to date.
user@host:~$ git checkout -b issue420
Switched to a new branch 'issue420'

Make and Commit a Code Change

user@host:~$ echo "git isn't that hard" >> somefile.txt
user@host:~$ git add somefile.txt
user@host:~$ git status
On branch issue420
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   somefile.txt
user@host:~$ git commit -m "Update some file"

Pull Changes from Upstream

The best way to get upstream changes is to preform a pull rebase. There are two things that can happen, either there are merge conflicts or not.

No Merge Conflicts

If there are no conflicts, great, your commits are replayed ontop of the master repo without any backwards merges.

user@host:~$ git pull --rebase upstream master
From https://github.com/googleinterns/step23-2020
 * branch            master    -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: Update some file

Merge Conflicts

If someone else edited the same file in a way that git can't automatically reconcile, you will have merge conflicts to resolve, let's see what happens in that case:

user@host:~$ git pull --rebase upstream master
From https://github.com/googleinterns/step23-2020
 * branch            master    -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying:  Update some file
Using index info to reconstruct a base tree...
M	somefile.txt
Falling back to patching base and 3-way merge...
Auto-merging somefile.txt
CONFLICT (content): Merge conflict in somefile.txt
error: Failed to merge in the changes.
Patch failed at 0001  Update some file
hint: Use 'git am --show-current-patch' to see the failed patch
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

Git is telling us there is a merge conflict. We can see which files have the merge conflict (unmerged) using the status command:

user@host:~$ git status
rebase in progress; onto 189aabe
You are currently rebasing branch 'issue420' on '189aabe'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)

Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
	both modified:   somefile.txt

no changes added to commit (use "git add" and/or "git commit -a")

We can open up the file and see what the conflict is.

user@host:~$ cat somefile.txt 
<<<<<<< HEAD
git is pretty fun
=======
git isn't that hard
>>>>>>>  Update some file

So we can see that someone put the line git is pretty fun into the same file. Everything between <<<<<<< HEAD and ======= is from the repository. Everything between ======= and >>>>>>> Update some file is the changes we made. Note that the >>>>>>> marker has the commit where the merge conflict occurs.

It's up to us to figure out what we want to keep. For this file let's keep both lines and just delete the conflict markers.

user@host:~$ cat somefile.txt 
git is pretty fun
git isn't that hard

So now that the file is how we want it, we can finish the rebase:

user@host:~$ git add somefile.txt
user@host:~$ git rebase --continue
Applying:  Update some file

Note that if you have many commits causing merge conflicts you may need to repeat this process a few times.

Pushing Changes

You should push changes to your personal fork, origin, to create a pull request from.

user@host:~$ git push -u origin issue420
Enumerating objects: 1191, done.
Counting objects: 100% (1178/1178), done.
Delta compression using up to 8 threads
Compressing objects: 100% (500/500), done.
Writing objects: 100% (1132/1132), 107.92 KiB | 21.58 MiB/s, done.
Total 1132 (delta 397), reused 1053 (delta 352)
remote: Resolving deltas: 100% (397/397), completed with 18 local objects.
remote: 
remote: Create a pull request for 'issue420' on GitHub by visiting:
remote:      https://github.com/KoopaKing/step23-2020/pull/new/issue420
remote: 
To https://github.com/KoopaKing/step23-2020.git
 * [new branch]      issue420 -> issue420
Branch 'issue420' set up to track remote branch 'issue420' from 'origin'.

If you have preformed a pull --rebase for the branch after having started a pull request (this is normal!) you will have an existing branch with a different history. This will cause the repo to reject a normal push.

user@host:~$ git push -u origin issue420     
To https://github.com/KoopaKing/step23-2020.git
 ! [rejected]        issue420 -> issue420 (non-fast-forward)
error: failed to push some refs to 'https://github.com/KoopaKing/step23-2020.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

You will need to use the -f option to overwrite that history to update your branch, and therefore pull request.

user@host:~$ git push -uf origin issue420     
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 282 bytes | 282.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/KoopaKing/step23-2020.git
 + 236e6b6...28d38fe issue420 -> issue420 (forced update)
Branch 'issue420' set up to track remote branch 'issue420' from 'origin'.

Conclusion

Now your branch and pull request are up to date without merge conflicts! Just like the file says, git isn't that hard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment