Speed Up Your Dev Skills With Using git Through The Shell
Let’s say you are already convinced that using git through the terminal is best comparing to trusting a UI tool. This quick tutorial will cover 80% of the common actions for you to see how easy and fun git through the terminal is.
Assuming you work on a MacOS:
It is hard to drive a car when you can’t see the road
Do yourself a favour and install a modern shell first! I recommend iterm2 + zsh + oh-my-zsh
brew install zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
Now you can know immediately what is the current checked out branch you are on, the status, etc...
Make the basic flow of development
(starting with working directly on master for simplicity, later showing work with branch):
➜ git clone git@github.com:look4regev/git_lab.git
Cloning into 'git_lab'...
remote: Counting objects: 58, done.
remote: Total 58 (delta 0), reused 0 (delta 0), pack-reused 58
Receiving objects: 100% (58/58), 2.18 MiB | 265.00 KiB/s, done.
Resolving deltas: 100% (12/12), done.
➜ cd git_lab
➜ git_lab git:(master) git pull -r # Pull latest with rebase
Already up to date.
Current branch master is up to date.
➜ git_lab git:(master) git status
On branch master
Your branch is up to date with 'origin/master'.nothing to commit, working tree clean
➜ git_lab git:(master) echo "\n hello" >> moshe.txt # Make changes
➜ git_lab git:(master) ✗ git status
On branch master
Your branch is up to date with 'origin/master'.Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)modified: moshe.txtno changes added to commit (use "git add" and/or "git commit -a")
➜ git_lab git:(master) ✗ git diff
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
modified: moshe.txt
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
@ moshe.txt:6 @
Guess What ?Oh My Fucking God !
\ No newline at end of file
Oh My Fucking God !
hello
➜ git_lab git:(master) ✗ git commit -am "Add all files to commit in one command"
[master 24ee76e] Add all files to commit in one command
1 file changed, 2 insertions(+), 1 deletion(-)
➜ git_lab git:(master) git push
Simple right? Let’s recape:
- Clone the repo
- Pull it (if it was already cloned)
- Check for status
- Make changes
- See the changes (Highly recommended to work also with diff-so-fancy)
- Commit
- Push
Now to work with a branch
➜ git_lab git:(master) git pull -r
Already up to date.
Current branch master is up to date.
➜ git_lab git:(master) git checkout -b mywork # Create a new branch and checkout
Switched to a new branch 'mywork'
➜ git_lab git:(mywork) echo "hello from branch" >> moshe.txt
➜ git_lab git:(mywork) ✗ git status
On branch mywork
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)modified: moshe.txtno changes added to commit (use "git add" and/or "git commit -a")
➜ git_lab git:(mywork) ✗ git diff
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
modified: moshe.txt
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
@ moshe.txt:6 @
Guess What ?Oh My Fucking God !
\ No newline at end of file
Oh My Fucking God !hello from branch
➜ git_lab git:(mywork) ✗ git commit -am "Commit from branch"
[mywork 01de354] Commit from branch
1 file changed, 1 insertion(+), 1 deletion(-)
➜ git_lab git:(mywork) git push --set-upstream origin mywork
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 315 bytes | 315.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
remote:
remote: Create a pull request for 'mywork' on GitHub by visiting:
remote: https://github.com/look4regev/git_lab/pull/new/mywork
remote:
To github.com:look4regev/git_lab.git
* [new branch] mywork -> mywork
Branch 'mywork' set up to track remote branch 'mywork' from 'origin'.
Pretty much the same except for the use of a new branch and pushing it to origin. Now to make a PR, let’s say in Github in this case- look how nice they are to suggest us the direct link to make a PR from this newly created branch. To merge the branch to master I recommend do it from the Github:
Be advised, when you merged from github it means that now your local repo is out of sync so to get the latest master changes:
➜ git_lab git:(mywork) git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
➜ git_lab git:(master) git pull -r
Now that was easy.
Aliases
If it looks long and tedious to write all this text, remember you can have quick aliases for everything. For your few weeks with the terminal make the full commands to make sure you know what is happening but then you can move to use the suite of aliases that are automatically installed with oh-my-zsh such as:
gpsup # git push --set-upstream origin mybranch
Problems
Get latest Changes from master
➜ git_lab git:(mywork) git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
➜ git_lab git:(master) git pull -r
git checkout -
Already up to date.
Current branch master is up to date.
➜ git_lab git:(master) git checkout - # Go back to last branch
Switched to branch 'mywork'
Your branch is up to date with 'origin/mywork'.
➜ git_lab git:(mywork) git rebase master # Put the branch ahead of master
Current branch mywork is up to date.
➜ git_lab git:(mywork) git push -f # You changed the history so must push force
Conflicts
When getting changes from master or to master you’ll probably have conflicts from other people’s changes. Don’t be panic, this is how you handle it like a boss:
➜ git_lab git:(mywork) git rebase master # Read what happens:
First, rewinding head to replay your work on top of it...
Applying: Commit from branch
Using index info to reconstruct a base tree...
M moshe.txt
Falling back to patching base and 3-way merge...
Auto-merging moshe.txt
CONFLICT (content): Merge conflict in moshe.txt
error: Failed to merge in the changes.
Patch failed at 0001 Commit from branch
Use 'git am --show-current-patch' to see the failed patchResolve 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_lab git:(549c327) ✗ cat moshe.txt # Git shows you the conflict:
123Guess What ?<<<<<<< HEAD
Oh My Fucking God !Big mess
=======
Oh My Fucking God !hello from branch
>>>>>>> Commit from branch
➜ git_lab git:(549c327) ✗ vi moshe.txt # Editing and fixing the file
➜ git_lab git:(549c327) ✗ cat moshe.txt # See how I want the final version will be:
123Guess What ?Oh My Fucking God !Big mess->hello from branch
➜ git_lab git:(549c327) ✗ git add moshe.txt # Mark the conflicts were resolved
➜ git_lab git:(549c327) ✗ git rebase --continue # Notice the branch is coming back to "mywork" after being on detached
➜ git_lab git:(mywork) git push -f
Recap of conflict resolving:
I rebased master to my branch which made a conflict. After editing and solving the conflict I am adding the file and continuing the rebase. At the end important to notice to push force again because the history was changed. If something goes off in the middle of the rebase you can always cancel it:
git rebase --abort
Summary
The terminal is great and gives a lot of visibility to what you’re doing. With time you’ll figure it easily how to solve edge cases but this workflow I gave you is sufficient to get you started. The terminal is your best friend once you know how to use it. Hope that this article made you closer ;)
Feel free to give a clap^)^ and connect through my Linkedin :) Regev.