Advanced Git Irina Gulina Tomas Tomecek February 27, 2020 Agenda ● [recap] What is Git? ● [recap] Git Basics ● Branching ● Collaborating ● Handy Git tools and commands ● Git Etiquette http://bit.ly/devconf19-gtw 2 What is Git? Distributed version control system for managing source code, i.e. it’s a system to ● record and save each file change ● restore a previous version of your code at any time 3 4 What problem does it solve? ● Keep track of code history ● Collaborate on code as a team ● See who made which changes 5 Basic Git workflow ● Modifying files in the working tree ● Staging changes in index ● Committing files to a repository 6 What Git commands do you know? 7 Do you know how to ... ● Create a new repository locally? ● Clone an existing remote repository? ● Check status of your changes? ● Record changes locally? ● Commit changes to a remote repository? ● Find info about Git commands? 8 Git Basic Commands ● help ● init ● clone ● config 9 ● add ● status ● diff ● commit ● reset ● mv ● rm ● branch ● checkout ● merge ● log ● stash ● fetch ● pull ● push ● remote Git help Documentation www.git-scm.com/docs $ git help $ git help 10 Git Branching 11 Branching 12 ● Default branch ● Create a new branch ● Switch branches ● Work in parallel on different branches ● Merge branches ● Delete a branch ● Rename a branch ● *Stash changes ● Resolve merge conflicts ● Rebase a branch Branching $ git branch $ git branch -v 13 Create a branch $ git branch testing $ git branch $ git branch -a 14 Switch a branch $ git checkout testing $ git switch testing $ git branch 15 Create and switch $ git checkout -b testing 16 Work in parallel $ touch file.txt $ git commit -a -m “add file.txt” 17 Work in parallel $ git checkout master 18 Work in parallel $ touch file2.txt $ git commit -a -m “add file2.txt” 19 Merge branches $ git checkout master $ git merge hotfix 20 Merge branches $ git checkout master $ git merge hotfix 21 Merge branches $ git branch -d hostfix $ git checkout iss53 $ vi index.html $ git commit a -m “fix link [issue 53]” 22 Merge branches $ git checkout master $ git merge iss53 23 Merge strategies $ git merge -s recursive branch1 branch2 $ git merge -s resolve branch1 branch2 $ git merge -s octopus branch1 branch2 branch3 branchN $ git merge -s ours branch1 branch2 branchN $ git merge -s subtree branchA branchB 24 Merge conflicts ● Git fails to start the merge error: Entry '' not uptodate. Cannot merge. (Changes in working directory) ● Git fails during the merge error: Entry '' would be overwritten by merge. Cannot merge. (Changes in staging area) 25 Create a merge conflict ● Create a Git repo ● Add some text into a file ● Commit the change ● Create a new branch ● Overwrite text in that file and commit it ● Updata the same file again on master, commit it ● Try to merge those two branches 26 Resolve a merge conflict ● Identify the conflict ● Inspect it ● Make changes ● Stage those changes $ git status $ git checkout $ git merge --abort $ git log --merge $ git reset --mixed $ git reset $ git diff $ git mergetool 27 Delete a branch ● You can’t remove a branch you checked out at ● You can remove a merged branch ● You can remove a branch with unstaged changes ● Sometimes you need to apply force $ git branch -d branch_name $ git branch -D branch_name 28 Stash changes ● Stashing your changes ● Re-applying your stashed changes ● Stashing untracked and ignored files ● Multi stashing ● Viewing stash diff ● Create a branch from stash ● Cleaning up your stash 29 $ git stash $ git stash pop $ git stash apply $ git stash -u $ git stash -a $ git stash list $ git stash pop stash@{2} $ git stash show $ git stash show -p $ git stash drop stash@{1} $ git stash clear Rebasing (cherry-pick) ● Pick commits on your current branch 30 $ git cherry-pick $commit Rebasing $ git checkout iss53 $ git rebase master 31 Multiple undo/redo of several local commits Scenario: There is a dozen or so commits, but only some of them are needed to be pushed, others changed or deleted 32 Solution: $ git rebase -i HEAD~5 don’t include any commit you’ve already pushed. Notice the order of commits. - Reordering commits - Squashing - Splitting git rebase -i $ git rebase -i HEAD~5 pick 21c701d Implement this new awesome feature pick 45ac7d7 Fix this nasty problem pick 7aep34d Adding docs pick d92923c No idea what I was doing? pick 95aa1c0 WIP 33 Collaborating 34 Collaborating 35 ● Add remote repositories ● Download remote content ● Upload local content to a remote repository $ git remote add origin $ git fetch origin $ git fetch --all $ git fetch --dry-run $ git fetch branch_name $ git merge origin/master $ git pull $ git pull --verbose $ git push $ git push --all $ git push --force How to find things 36 Revision selectors 1. 1c002dd4b536e7479fe34593e72e6c6c1819e53b 2. 1c002dd changed the version number 085bb3b removed unnecessary test code a11bef0 first commit 37 $ git log --oneline Revision selectors 3. $ git reflog 38 734713b HEAD@{0}: commit: fixed refs handling, added gc d921970 HEAD@{1}: merge phedders/rdocs: Merge made by the 'recursive' strategy. 1c002dd HEAD@{2}: commit: added some blame stuff 1c36188 HEAD@{3}: rebase -i (squash): updating HEAD 95df984 HEAD@{4}: commit: # This is a combination of two Revision selectors 4. $ git show master@{yesterday} $ git show master@{2.months.ago} 39 5. Ancestry references (^ ~) ● ca82a6d^ ● ca82a6d^^ ● HEAD ● HEAD^ ● HEAD^2 (is it the same as ca82a6d^^ ?) ● HEAD~ (is it the same as HEAD^ ?) ● HEAD~2 (is it the same as HEAD^2 ?) ● HEAD~3^2 (is it valid?) Revision selectors 40 Revision selectors 6. Ranges of commits How to show commits on experiment branch, which are not on master? The opposite? How to show local commits which are not on origin remote? 41 Solution: $ git log master..experiment $ git log experiment..master Revision selectors 7. Multiple points How to see what commits are in any of several branches, that aren’t in the branch you’re currently on? How to see all commits on A and B, which are not on C? More than two references can be specified. 42 Solution: $ git log A B ^C $ git log A B --not C Revision selectors 8. Scenario: How to see what commits are in either of two branches, but not on both of them? i.e. E, F, C, D? 43 Solution: $ git log master...experiment Git Log Searching Problem: How to find specific commits by the content of their messages or even the content of the diff they introduce? 44 Solution: $ git log -S calc --oneline 61e3ce7 add a new function $ git log -S x1 --oneline 18f3671 change params in search a5c51ae edit search func 7a7c4f7 add search func Git Log Searching Problem: How to show the history (all commits) of a function or line of code in a codebase? 45 Solution: $ git log -L :add: Local troubles 46 Git cardinal rule 47 You have a great freedom to rewrite your history locally Steps to reproduce: The cat walked across your keyboard, while you were making coffee. You have not noticed and saved the changes, then saw them with git diff. Undoing local changes, not committed 48 Solution: $ git checkout -- Changing the last local commit 1. How to modify the last commit message 49 Solution: $ git commit --amend Changing the last local commit 2. How to modify the content of the last commit 50 Solution: Make changes Stage those changes $ git commit --amend or $ git commit --amend --no-edit Don’t amend your last commit if you have already pushed it! Undo the last local commit(s) Solution: $ git reset or $ git reset --hard 51 Find and restore a deleted file Scenario: A file was deleted and this change was committed. More commits were added. How to find a commit deleting that file and restoring it? 52 Solution: 1) $ git rev-list -n 1 HEAD -- path/to/file $ git checkout ^ -- path/to/file Delete and restore all files Scenario: $ rm -r * 53 Redo after undo the last local commit(s) Scenario: You made some commits, then did a git reset --hard to “undo” them, and then you want those changes back. There are several possible solutions, it depends on what you want to accomplish. 54 Solution: $ git reflog - $ git reset --hard - $ git checkout -- - $ git cherry-pick Revert a single file to a specific commit Scenario: Some changes on a file were committed multiple times. Then, an author wants to restore that file to a specific commit 55 Solution: $ git log $ git diff $ git checkout -- filename or if one commit before a specific one: $ git checkout ~1 filename Stop tracking a tracked file Scenario: A log file was accidently added (by commit) to the repository. Since then Git reports there are unstaged changes in that file even though there is *.log entry in .gitignore. 56 Solution (remove a file from a git repo, but not locally) $ git rm --cached file.log for a single directory $ git rm --cached -r logs Question: How to remove multiple files? Fix an earlier local commit Scenario: A file was not included in an earlier commit. 57 Solution: $ git add $ git commit --fixup $ git rebase -i --autosquash 07 Removing a file from every commit Scenario: Remove a file (e.g. with a sensitive info) from the entire history. 58 Solution: $ git filter-branch --tree-filter ‘rm -f id_rsa’ HEAD Rewrite 6b9b3cf04e7c5686a9cb838c3f36a8cb6a0fc2bd (21/21) Ref 'refs/heads/master' was rewritten Moving local commits between branches Scenario: Commits were made on a master branch, but they should be on another branch instead 59 Solution: $ git branch feature What is the difference with git checkout -b feature? $ git reset --hard origin/master $ git checkout feature How to avoid it? Outdated branch Scenario: You commited changes to one feature branch based on master which was pretty far behind remote master. You wish your feature branch be up-to-date with the remote master and your commits be on top of that. 60 Solution: $ git checkout master $ git pull $ git checkout feature $ git rebase master Restore a deleted branch Scenario: You deleted a branch in your Git repository, but want it back. 61 Solution: Find a SHA of that branch from terminal history or git reflog $ git checkout -b Save changes without committing Scenario: You made some code changes, but it’s not a good time to commit. You need to switch branches to fix an urgent bug. How to save your work? 62 Solution: $ git stash Find the commit, that introduced a bug Scenario: You created several commits, but from some certain point the application gets broken. It’s unclear what it caused and which commit introduced the bug. 63 Solution: $ git bisect Public troubles 64 Undo a commit, pushed Steps to reproduce: $ touch file.txt $ git add file.txt $ git commit -m “Something terribly wrong” $ git push origin master 65 Undo a commit, pushed Solution: Find SHA hash of that commit. $ git revert $ git push It’s the safest scenario, it doesn’t alter history! 66 How to restore orphaned or deleted commits Steps to reproduce: $ git reset --hard HEAD~1 $ git push --force 67 How to restore orphaned or deleted commits Solution: ● Find SHA hash of that commit. ● Create a new branch with that commit as the head of the branch $ git branch my-new-branch ● Ensure all changes are on that branch ● Merge changes to master 68 Edit the message of older or multiple commit(s), pushed Solution: 1) $ git commit --amend $ git push --force 2) $ git rebase -i HEAD~5 # Display last 5 commits or git rebase -i Replace pick with reword in opened editor Edit the commit messages Save and close the file $ git push --force 69 Avoid repeated merge conflicts Scenario: 70 Solution: $ git rerere Rename a branch Scenario: You made a spelling mistake in a branch name. Instead of bugfix-15631 you named it idontknow. Maybe you were hungry that moment. Now you want to rename it. 71 Solution: $ git branch -m $ git push origin : $ git push origin --set-upstream Git Etiquette 72 73 Poor quality code can be refactored. A terrible commit message lasts forever. What is a commit message 74 ● Title/Subject line ● Body Commit message example 75 commit Author: Date: Mon Apr 2 15:10:03 2018 -0400 Change how workers are represented * Don't serialize the 'gracefully_shutdown' field * Create a new 'missing' property and serialize it * In the status API, list both online and missing workers Requires PR: https://github.com//pull/921 closes #3544 https://.plan.io/issues/3544 Commit Title or Subject line Commit Body Usage of a commit title 76 ● git log --pretty=oneline ● git rebase --interactive ● merge.summary ● git shortlog ● git format-patch, git send-email, … ● reflogs ● Gitk ● GitHub user interface Commit history 77 $ git log --oneline cf2***e some updates 7ae***f some structure changes 10e***d todo 1b4***1 improved hj3***b docs 47a***m some updates 871***a little bit reworked and added specific part for docker type What constitutes a good commit title? 78 ● git commit -m "Fix login bug" ● git commit or git commit --verbose Redirect user to the requested page after login https://link/to/issue/tracker What constitutes a good commit title? 79 ● Capital letter, 50/72, no punctuation in the end $ git commit A brief summary of the commit A paragraph describing what changed and its impact." What constitutes a good commit title? 80 ● compare to the linux kernel contributors $ git shortlog |\ grep -e '^ ' |\ sed 's/[[:space:]]\+\(.*\)$/\1/' |\ awk '{lens[length($0)]++;} END {for (len in lens) print len, lens[len] }' |\ sort -n What constitutes a good commit title? 81 What constitutes a good commit title? 82 ● Present Tense and Imperative Mood “If accepted, this commit will .” cf****e Adds unit tests 7a****f Fixed unit tests 10****d Update unit tests 1b****1 Removing unit test What constitutes a good commit title? 83 ● Reference to an issue Redirect user to the requested page after login https://link/to/issue/tracker What constitutes a good commit title? 84 ● Clear Title - What is commit about? ● Present Tense and Imperative Mood ● Clear Body - Why is it needed? ● 50/72 ● Reference to an issue Git push 85 86 IF YOU DO FORCE PUSH…. May the force stay with you. Submitting a PR 87 Why do we use PR workflow 88 ● Share changes ● Get review and feedback ● Encourage quality What constitutes a good PR? 89 ● Complete piece of work ● Adds value in some way ● Solid title and body ● Clear commit history ● Small Contributors 90 ● Follow the repo’s conventions ● Double check your code (and ToDos) ● Add docs ● Keep changes small ● Separate branch ● Be clear and specific ● Check your ego and be polite Before submitting a PR Contributors 91 After submitting a PR ● Check your ego and be polite ● Ensure your branch merge and tests pass ● Use --amend, --fixup or rebase -i ● Don’t merge your own PR WIP PR? 92 ● Don’t overuse WIP label ● Remove WIP label when ready ● “This is ready for review, please.” Reviewing a PR 93 Reviewers 94 ● Be kind and polite ● Check commit history ● Don’t fix issues ● Ensure the branch can be merged ● CI Tests pass ● Don’t merge WIPs ● Squash ● Delete branch Thank you! igulina@redhat.com ttomecek@redhat.com