Git setup for success. In this example I'll be solving fictional issue #420.
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)
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'
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"
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.
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
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.
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'.
Now your branch and pull request are up to date without merge conflicts! Just like the file says, git isn't that hard
.