Advanced Git DAVID PARSONS 1 Reminders DAVID PARSONS ADVANCED - - PowerPoint PPT Presentation

advanced git
SMART_READER_LITE
LIVE PREVIEW

Advanced Git DAVID PARSONS 1 Reminders DAVID PARSONS ADVANCED - - PowerPoint PPT Presentation

Advanced Git DAVID PARSONS 1 Reminders DAVID PARSONS ADVANCED GIT 2 Generali(es DAVID PARSONS - ADVANCED GIT 3 Two fundamental rules ! Commit o5en Keep commits small and commit together only related changes (commit = minimal


slide-1
SLIDE 1

Advanced Git

DAVID PARSONS

slide-2
SLIDE 2

DAVID PARSONS – ADVANCED GIT 2

Reminders

1

slide-3
SLIDE 3

DAVID PARSONS - ADVANCED GIT 3

Generali(es

slide-4
SLIDE 4

DAVID PARSONS - ADVANCED GIT 4

Two fundamental rules !

  • Commit o5en
  • Keep commits small and commit together only related

changes (commit = minimal independent changeset)

  • Write clear and informa(ve logs
  • A log should enable its reader to:

1. Iden(fy at a glance the ra(onale behind the commit 2. Have detailed explana(on if needed

  • Template for logs (from hJp://git-scm.com/book/ch5-2.html)

Short (50 chars or less) summary of changes More detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some contexts, the first line is treated as the subject of an email and the rest of the text as the body. The blank line separa(ng the summary from the body is cri(cal (unless you omit the body en(rely).

slide-5
SLIDE 5

DAVID PARSONS - ADVANCED GIT 5

Local Repo

From working copy to remote repo

Working Copy Staging Area CommiJed Revisions Remote Repo CommiJed Revisions

Remote Local

NB: This is a “bare” repo, it has no working copy nor staging area

slide-6
SLIDE 6

DAVID PARSONS - ADVANCED GIT 6

File Status Lifecycle

slide-7
SLIDE 7

DAVID PARSONS - ADVANCED GIT 7

Managing conflicts

slide-8
SLIDE 8

DAVID PARSONS - ADVANCED GIT 8

Log rev 1 Log rev 2 Log rev 3 Add content to foo Add file baz Add content to bar v0.1 Modify bar Change bar $ git merge master

Managing conflicts

r/o/master

slide-9
SLIDE 9

DAVID PARSONS - ADVANCED GIT 9

$ git merge Auto-merging bar CONFLICT (content): Merge conflict in bar Automatic merge failed; fix conflicts and then commit the result. $

Managing conflicts

Log rev 1 Log rev 2 Log rev 3 Add content to foo Add file baz Add content to bar v0.1 Modify bar Change bar master r/o/master

slide-10
SLIDE 10

DAVID PARSONS - ADVANCED GIT 10

$ git merge Auto-merging bar CONFLICT (content): Merge conflict in bar Automatic merge failed; fix conflicts and then commit the result. $ $ cat bar This is line 1 This is line 2 This is line 3 <<<<<<< HEAD This is the fourth line ======= This is line number 4 >>>>>>> featureA This is line 5 This is line 6 This is line 7 This is line 8 $

Managing conflicts

Log rev 1 Log rev 2 Log rev 3 Add content to foo Add file baz Add content to bar v0.1 Modify bar Change bar master r/o/master

slide-11
SLIDE 11

DAVID PARSONS - ADVANCED GIT 11

$ # You can edit the conflicting files directly and then stage them and commit, or you can use a merge tool $ $ git mergetool

Managing conflicts

Log rev 1 Log rev 2 Log rev 3 Add content to foo Add file baz Add content to bar v0.1 Modify bar Change bar master r/o/master

slide-12
SLIDE 12

DAVID PARSONS - ADVANCED GIT 12

mergetool – p4merge

slide-13
SLIDE 13

DAVID PARSONS - ADVANCED GIT 13

$ git config --global merge.tool meld $ git config --global mergetool.meld.cmd 'meld $LOCAL $MERGED $REMOTE' $ git config --global mergetool.meld.trustExitCode false $

Configuring a mergetool

slide-14
SLIDE 14

DAVID PARSONS – ADVANCED GIT 14

Things to know

2

slide-15
SLIDE 15

DAVID PARSONS - ADVANCED GIT 15

Configuring git

# Configure your name and e-mail address (almost mandatory) $ git config --global user.name "David Parsons" $ git config --global user.email david.parsons@inria.fr $ $ # Configure the editor git will open when needed $ git config --global core.editor nano $ $ # Setup a few aliases, either simple shorthands... $ git config --global alias.co checkout $ git config --global alias.ci commit $ git config --global alias.s status $ $ # ... or including options $ git config --global alias.lg "log --pretty=format:\"%h - %an : %s\"" $ $ # You can even create new commands $ git config --global alias.unstage "reset HEAD”

slide-16
SLIDE 16

DAVID PARSONS - ADVANCED GIT 16

Detached HEAD ?

slide-17
SLIDE 17

DAVID PARSONS - ADVANCED GIT 17

Detached HEAD ?

  • You are in detached HEAD when you are not “on” any

branch

  • Most of the (me, this happens when you provide anything

that is not a branch to git checkout. E.g. a tag, a SHA-1, an indirect reference (HEAD~1)

  • You can also use --detach when providing a branch name
  • When in detached HEAD, you can commit as you like ;

but be wary of the garbage collector, it could very well erase your work if you do not pay aJen(on !

  • My advice: always create a branch to commit your

work to, it costs nothing to create a “tmp” branch and delete it when you do not need it any longer.

slide-18
SLIDE 18

DAVID PARSONS - ADVANCED GIT 18

Detached HEAD ?

$ Add file foo Add file bar Modify foo v0.1 Add file baz featureA master fed7 a56f abcd 1234

slide-19
SLIDE 19

DAVID PARSONS - ADVANCED GIT 19

Detached HEAD ?

$ git checkout v0.1

Note: checking out 'v0.1'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b new_branch_name HEAD is now at abcd1b3... Add file bar

$ Add file foo Add file bar Modify foo v0.1 Add file baz featureA master fed7 a56f abcd 1234

slide-20
SLIDE 20

DAVID PARSONS - ADVANCED GIT 20

Detached HEAD ?

$ git rm foo $ g ci -m ”Remove file foo” [detached HEAD be4b243] Remove file foo 1 file changed, 1 deletion(-) delete mode 100644 foo $ Add file foo Add file bar Modify foo v0.1 Add file baz featureA master fed7 a56f abcd 1234 Remove file foo be4b

slide-21
SLIDE 21

DAVID PARSONS - ADVANCED GIT 21

Detached HEAD ?

$ git rm foo $ g ci -m ”Remove file foo” [detached HEAD be4b243] Remove file foo 1 file changed, 1 deletion(-) delete mode 100644 foo $ g s HEAD detached from v0.1 nothing to commit, working directory clean $ Add file foo Add file bar Modify foo v0.1 Add file baz featureA master fed7 a56f abcd 1234 Remove file foo be4b

slide-22
SLIDE 22

DAVID PARSONS - ADVANCED GIT 22

Detached HEAD ?

$ git co -b featureB Switched to a new branch ’featureB’ $ Add file foo Add file bar Modify foo v0.1 Add file baz featureA master fed7 a56f abcd 1234 Remove file foo be4b featureB

slide-23
SLIDE 23

DAVID PARSONS - ADVANCED GIT 23

Remote tracking and Upstream branches

slide-24
SLIDE 24

DAVID PARSONS - ADVANCED GIT 24

Remote tracking branches

$ git branch # List local branches featureA * master $ git branch -r # List remote-tracking branches

  • rigin/master

$ git branch -a # List both local and remote-tracking branches featureA * master

  • rigin/master

# Question: what happens when you check out a remote tracking branch? Add file foo Add file bar Modify foo v0.1 Add file baz featureA master 7656 de90 abcd 1234 remotes/origin/master

slide-25
SLIDE 25

DAVID PARSONS - ADVANCED GIT 25

Upstream branches

$ git pull # What exactly does git pull do (or try to do)? Add file foo Add file bar Modify foo v0.1 Add file baz featureA master 7656 de90 abcd 1234 remotes/origin/master

slide-26
SLIDE 26

DAVID PARSONS - ADVANCED GIT 26

Upstream branches

$ git pull There is no tracking information for the current branch. Please specify which branch you want to merge with. See git-pull(1) for details git pull <remote> <branch> If you wish to set tracking information for this branch you can do so with: git branch --set-upstream-to=origin/<branch> master $ Add file foo Add file bar Modify foo v0.1 Add file baz featureA master 7656 de90 abcd 1234 remotes/origin/master

slide-27
SLIDE 27

DAVID PARSONS - ADVANCED GIT 27

Upstream branches

$ git branch -vv featureA 7656d7c Add file baz * master de90ac4 Modify foo $ git branch -u origin/master Branch master set up to track remote branch master from origin. $ git branch -vv featureA 7656d7c Add file baz * master de90ac4 [origin/master] Modify foo $ git pull Already up-to-date. $ Add file foo Add file bar Modify foo v0.1 Add file baz featureA master 7656 de90 abcd 1234 remotes/origin/master

slide-28
SLIDE 28

DAVID PARSONS – ADVANCED GIT 28

Git internals (dive into .git)

3

slide-29
SLIDE 29

DAVID PARSONS – ADVANCED GIT 29

Small interesting tools

4

slide-30
SLIDE 30

DAVID PARSONS - ADVANCED GIT 30

Crea(ng and applying patches

slide-31
SLIDE 31

DAVID PARSONS - ADVANCED GIT 31

Patches

  • For some reason, you could want to send one or more

changesets to a collaborator without actually pushing

  • There are basically 2 ways of doing that

Ø For a single changeset, whether it has been commiJed

  • r not, you can use git diff to generate a plain

patch and git apply to apply it Ø For one or more commiJed changesets, you can use git format-patch to generate a series of patches and git am to apply them (this will preserve the original commiJer name)

slide-32
SLIDE 32

DAVID PARSONS - ADVANCED GIT 32

Cherry-picking

slide-33
SLIDE 33

DAVID PARSONS - ADVANCED GIT 33

Cherry-picking

  • You have spoJed a commit made in an otherwise very

messy branch and you would love to retrieve that commit (and only that one) in your branch ? Ø Yes, you could create and apply a patch… Ø Or you could use the feature that was created for that very purpose: cherry-picking

  • This is only made possible by s(cking to the atomic

commits rule !!!

slide-34
SLIDE 34

DAVID PARSONS - ADVANCED GIT 34

Cherry-picking

# Cherry-pick a fabulous commit: $ git cherry-pick <a-fabulous-commit> […] # Cherry-pick a sequence of contiguous fabulous commits: $ git cherry-pick <parent-of-first-in-seq>..<last-in-seq> […] # Get bored of typing c h e r r y - p i c k $ git config --global alias.cp cherry-pick

slide-35
SLIDE 35

DAVID PARSONS - ADVANCED GIT 35

Cherry-picking

  • Really easy and very handy
  • Allows you to apply the changes introduced by one or

more commits on top of HEAD

Add file foo Modify foo Add baz featureA master fed7 a56f 1234 Remove foo be4b Add file foo Modify foo Add baz featureA master fed7 a56f 1234 Remove foo be4b Add baz 34f5 $ git cp fed7

slide-36
SLIDE 36

DAVID PARSONS - ADVANCED GIT 36

“Par(al” commits

slide-37
SLIDE 37

DAVID PARSONS - ADVANCED GIT 37

“Par(al” commits

  • Commits should be atomic: a commit must introduce

a minimal independent changeset

  • Most programmers have difficul(es focusing on a

single task (did you just correct a typo while scrolling

  • ver the code in the midst of a bugfix ?)
  • git add --patch (or -p) is your friend !
  • git gui is your beJer friend, it allows you to add

parts of a file to your staging area on a per-hunk or even per-line basis

slide-38
SLIDE 38

DAVID PARSONS - ADVANCED GIT 38

git add -p

$ git add -p diff --git a/file b/file index e72f11f..75ad869 100644

  • -- a/file

+++ b/file @@ -1,7 +1,7 @@ ... ... ...

  • Original line

+ Modified line ... ... ... Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]?

  • Works fine for simple cases (tedious otherwise)
slide-39
SLIDE 39

DAVID PARSONS - ADVANCED GIT 39

Using git gui

slide-40
SLIDE 40

DAVID PARSONS - ADVANCED GIT 40

Stash

slide-41
SLIDE 41

DAVID PARSONS - ADVANCED GIT 41

Stash

# You’re working on something and need to switch to something else $ git co something-else Error: Your local changes to the following files would be overwritten by checkout: […] Please, commit your changes or stash them before you can switch branches. Aborting $ g stash [push –m “what you were doing”] Saved working directory and index state On dev: what you were doing HEAD is now at 0b0b9eb […] $ g stash list stash@{0}: On dev: what you were doing $

  • Literally “garder sous le coude”
slide-42
SLIDE 42

DAVID PARSONS - ADVANCED GIT 42

Stash

$ git co something-else # Now you can (WD is clean) Switched to branch 'something-else’ $ # Do whatever you needed to do on something_else # When you want to go back to ‘something’, # Checkout: $ g co something Switched to branch 'something’ # Recover what you have stashed: $ g stash pop # You’re back to initial state $

slide-43
SLIDE 43

DAVID PARSONS - ADVANCED GIT 43

Stash

  • Literally “garder sous le coude”
  • The stash is a stack (thus the push/pop terminology)
  • f commit objects
  • Warning: there can be conflicts when applying (or

pop-ing) stashed changes In the case of a pop, the corresponding stash will not be dropped, do not forget to do it a5er resolving the conflicts (git stash drop …)

  • A (very) useful op(on: --keep-index (or -k)

stashes only files in the “modified” state

slide-44
SLIDE 44

DAVID PARSONS - ADVANCED GIT 44

Git bisect

slide-45
SLIDE 45

DAVID PARSONS - ADVANCED GIT 45

git bisect

  • Found a bug ?

Have no idea when (or most importantly by whom) it was introduced ?

  • git bisect is your next friend on the list, it will
  • perate a dichotomic search in your commit tree
slide-46
SLIDE 46

DAVID PARSONS - ADVANCED GIT 46

git bisect

# Initiate dichotomic search $ g bisect start # Mark current commit as bad (has bug) $ g bisect bad # Tell git about a commit that is known to not have the bug $ g bisect good <a-known-good-commit> Bisecting: 27 revisions left to test after this (roughly 5 step) […] # Not sure about a “good” commit in the first place ? $ g co <possibly-good-commit> # Check manually => make check ? # If this commit is not “good”, you’ll have to go further back in # your history and check again. # Don’t hesitate to go far far back in your history, the idea is to # not drive the search yourself after all ;) $ git bisect good

slide-47
SLIDE 47

DAVID PARSONS - ADVANCED GIT 47

git bisect

# Once you have marked at least one good and one bad commit, the # dichotomic search will start. # Git will checkout commit after commit and ask you to mark them as # good or bad (you can also skip if you’re unsure) Bisecting: 27 revisions left to test after this (roughly 5 step) [<sha-1>] <commit-msg> $ git bisect good|bad Bisecting: 13 revisions left to test after this (roughly 4 step) [<sha-1>] <commit-msg> $ git bisect good|bad ab23ef is the first bad commit commit ab23ef Author: David Parsons <david.parsons@inria.fr> Date: … <commit message> List of modified files in the form: :<old mode> <new mode> <old blob> <new blob> XY <file name>

slide-48
SLIDE 48

DAVID PARSONS - ADVANCED GIT 48

git bisect

# Automate search: $ g bisect start HEAD <known-good> $ g bisect run make check […] ab23ef is the first bad commit […] # Building out of source ? You can use this: cat > run_make_check.sh ! /bin/bash cd build make check status=$? cd .. exit $status ^D $ chmod u+x run_make_check.sh $ g bisect run run_make_check.sh

slide-49
SLIDE 49

DAVID PARSONS – ADVANCED GIT 49

Time for Prac1cal Work !

  • Retrieve exercice document :

hJp://sed.inrialpes.fr/advancedgit-tuto Ø To Do : Sec1on 1 + Sec1on 2

slide-50
SLIDE 50

DAVID PARSONS – ADVANCED GIT 50

Rewriting History

5

slide-51
SLIDE 51

DAVID PARSONS - ADVANCED GIT 51

Rewri(ng History ?

# You’ve just commited something and realize you forgot to add a file $ git add the_forsaken_file $ git commit --amend # No one saw you ;)

Remember you have a local repository ? Everything you have not published (i.e. pushed) yet is strictly local to your repo. It is known by you and no one else. Since then, what is stopping you from modifying it ? This is one of my favourite things about git, I can be stupid and appear not to be !

WARNING: Do not do that if you’ve pushed the faulty commit !!!!!

slide-52
SLIDE 52

DAVID PARSONS - ADVANCED GIT 52

commit --amend

A5er using git commit -–amend, let’s look at what our commit graph looks like :

“Replacement” commit Faulty commit (e.g. missing a file). This commit is not referred to by any ref. It will eventually be garbage collected.

… Add new class Foo master Add new class Foo

slide-53
SLIDE 53

DAVID PARSONS - ADVANCED GIT 53

rebase

  • Rebase allows you to linearize a branching tree structure
  • Rebase literally means “set a new base” (for a branch)
  • In other words, rebasing a branch consists in telling git to :
  • 1. “Pick” a branch
  • 2. “Cut” it (somewhere)
  • 3. “GraB” it (somewhere else)

Add file foo Modify foo Add baz

  • ther

current fed7 a56f 1234 Remove foo be4b Add file foo Modify foo Add baz

  • ther

fed7 a56f 1234 be4b current Remove foo ef56 Rebased commit Original commit

slide-54
SLIDE 54

DAVID PARSONS - ADVANCED GIT 54

rebase: default behaviour

By default, git rebase:

  • picks the current branch
  • cuts it at its LCA (last common ancestor) with its upstream branch (if any)
  • graB it onto its upstream branch

Ø If your branch and its upstream were in sync, this means you’ve achieved to do nothing in a complicated way. Ø If you had a branching tree structure (e.g. a5er fetching your colleagues’ work – see example above), you’ve replayed your changes

  • n top of your colleagues’.

This is safe since it will only alter those commits you haven’t pushed yet

Add file foo Modify foo Add baz master fed7 a56f 1234 Remove foo be4b r/o/master

slide-55
SLIDE 55

DAVID PARSONS - ADVANCED GIT 55

rebase: one argument form

Branch master has been updated since you started to write your feature. You would like your feature to be up-to-date (to propose it as a pull-request ?)

$ git rebase master # Use master for cut and graft steps First, rewinding head to replay your work on top of it… Applying: …

Rebased commits Original commits

Add file foo Modify foo Add baz featureA master fed7 a56f 1234 Remove foo be4b Add file foo Modify foo Add baz master fed7 a56f 1234 Remove foo be4b Modify foo Add baz featureA 3f6e ac7e

slide-56
SLIDE 56

DAVID PARSONS - ADVANCED GIT 56

rebase: pick, cut, gra5

  • git rebase simplified synopsis:

$ git rebase […] [--onto <newbase>] [<upstream> [<branch>]]

What git rebase does (this is a lie…):

  • picks ‘branch’
  • cuts it at the LCA (last common ancestor) of ‘upstream’ and ‘branch’
  • graBs it onto newbase

Actually,

  • If ‘branch’ is specified, git rebase will be preceded by a git checkout ‘branch’
  • Nothing is “cut” and the LCA is all but a lie... The changes made by commits in ‘branch’

that are not in ‘upstream’ will be recorded and then replayed onto the new base. That means a cherry-picked commit will be ignored (and that is what we want !)

slide-57
SLIDE 57

DAVID PARSONS - ADVANCED GIT 57

git rebase

Log rev 1 Log rev 2 Log rev 3 Add content to foo Add file baz Add content to bar v0.1 Modify bar Change bar master remotes/origin/master $ git fetch $ # About to run git rebase

slide-58
SLIDE 58

DAVID PARSONS - ADVANCED GIT 58

$ git fetch $ git rebase … $ Modify bar master Change bar

Rebased commit Original commit (master was here)

Change bar remotes/origin/master Log rev 1 Log rev 2 Log rev 3 Add content to foo Add file baz Add content to bar v0.1

git rebase

slide-59
SLIDE 59

DAVID PARSONS - ADVANCED GIT 59

Rebase only local commits

Rebasing basically means re-wri1ng the history of what happened.

Ø This is a very powerful feature

But as always, “great power comes with great responsibility” :

DO NOT REBASE COMMITS THAT EXIST OUTSIDE YOUR REPOSITORY

slide-60
SLIDE 60

DAVID PARSONS - ADVANCED GIT 60

merge or rebase ?

slide-61
SLIDE 61

DAVID PARSONS - ADVANCED GIT 61

Which one would you prefer ?

Merge Rebase

merge or rebase ?

slide-62
SLIDE 62

DAVID PARSONS - ADVANCED GIT 62

merge or rebase ?

Or maybe this mixed one ?

Merge Rebase Mixed

slide-63
SLIDE 63

DAVID PARSONS - ADVANCED GIT 63

merge or rebase ?

G: So, some(mes you do want a “true merge”. P: Yes, but that is what git merge does right ? G: True… except when a fast-forward merge is possible. P: fast-forward merge ?

C0 C3 C2 feature dev C1 $ git merge feature C0 C3 C2 feature dev C1

slide-64
SLIDE 64

DAVID PARSONS - ADVANCED GIT 64

merge or rebase ?

C0 C3 C2 feature dev C1 C0 C3 C2 dev C1 feature Merged branch feature into dev $ git merge --no-ff feature

slide-65
SLIDE 65

DAVID PARSONS - ADVANCED GIT 65

Prefer fetch to pull

The pull command is equivalent to a fetch followed by a merge. So what you are really asking git to do when you pull is to merge your work with something you know nothing about (!) To come around this problem, start by fetching what is new from the remote and have a look at it. If what you really want is a merge, you can s(ll do it. But this (me, you will do it knowingly.

slide-66
SLIDE 66

DAVID PARSONS - ADVANCED GIT 66

Interac(ve rebase

slide-67
SLIDE 67

DAVID PARSONS - ADVANCED GIT 67

Interac(ve rebase

Remember what we did with git commit --amend ? Now imagine you did the exact same thing but have already added a few commits

  • n top of the faulty one.

You can not use commit –amend because it only allows to modify the commit that is referenced by HEAD. This is when interac1ve rebase becomes handy.

slide-68
SLIDE 68

DAVID PARSONS - ADVANCED GIT 68

Interac(ve rebase

$ git rebase –interactive # or $ git rebase -i

Let’s see what the command looks like : What you’re rebasing and onto what, follows the same rules as non-interac(ve rebase. The difference is that you will get to decide what to do with each commit to be rebased instead of uncondi(onally “pick” them

slide-69
SLIDE 69

DAVID PARSONS - ADVANCED GIT 69

Interac(ve rebase

slide-70
SLIDE 70

DAVID PARSONS - ADVANCED GIT 70

Interac(ve rebase

slide-71
SLIDE 71

DAVID PARSONS - ADVANCED GIT 71

Interac(ve rebase

… third commit (should have been before second commit) second commit first commit Correc(ng first commit second commit feature first commit commit 1bis (was « third commit … »)

slide-72
SLIDE 72

DAVID PARSONS – ADVANCED GIT 72

Undoing things

6

slide-73
SLIDE 73

DAVID PARSONS - ADVANCED GIT 73

Unstage

$ git status (use "git reset HEAD ..." to unstage) $ git reset HEAD <file> $ git config --global alias.unstage "reset HEAD" $ git unstage

Unstaging an en(re file is very easy, git tells you how to do it : Do not want to have to remember this command ? Create an alias : If you do not want to unstage the en(re file but only some parts of it, the easiest solu(on is probably : git gui. But you could also use : git reset -p

slide-74
SLIDE 74

DAVID PARSONS - ADVANCED GIT 74

Unmodify a file

$ git status (use "git checkout -- <file>..." to discard changes …) $ git co -- <file> $ git config --global alias.unmod "checkout --" $ git unmod <file>

Again, git is kind enough to prompt you for ac(ons you might want to do: And again you can create an alias: If you do not want to unmodify a whole file but only some parts of it, the easiest solu(on is probably a di+ool. But you could also use git co -p

slide-75
SLIDE 75

DAVID PARSONS - ADVANCED GIT 75

Undo a commit

$ git rebase -i ... $ git revert <commit-to-undo>

  • If the commit has not been published yet

This way, you can thoroughly remove the faulty commit from the history

This will create a new commit whose diff is the inverse of that of the commit to undo

  • If the commit has been published
slide-76
SLIDE 76

DAVID PARSONS - ADVANCED GIT 76

git reset

C0 C3 C2 feature master C1 C0 C3 C2 feature master C1

git reset can become very handy when things are beginning to get awry. It allows you to make a branch point anywhere you want. Let’s say you have commiJed stuff in master when what you really wanted was to commit them in feature : What you want What you have

slide-77
SLIDE 77

DAVID PARSONS - ADVANCED GIT 77

$ git co feature

git reset

C0 C3 C2 feature master C1 C0 C3 C2 feature master C1

What you want What you have

slide-78
SLIDE 78

DAVID PARSONS - ADVANCED GIT 78

$ git co feature Switched to branch 'feature' $ # ?

git reset

C0 C3 C2 feature master C1

What you want What you have

C0 C3 C2 feature master C1

slide-79
SLIDE 79

DAVID PARSONS - ADVANCED GIT 79

$ git co feature Switched to branch 'feature' $ git (merge | rebase | reset --hard) master

git reset

C0 C3 C2 feature master C1

What you want What you have

C0 C3 C2 feature master C1

slide-80
SLIDE 80

DAVID PARSONS - ADVANCED GIT 80

$ git co feature Switched to branch 'feature' $ git (merge | rebase | reset --hard) master ... $

git reset

C0 C3 C2 feature master C1

What you want What you have

C0 C3 C2 feature master C1

slide-81
SLIDE 81

DAVID PARSONS - ADVANCED GIT 81

$ git co feature Switched to branch 'feature' $ git (merge | rebase | reset --hard) master ... $ git co master Switched to branch 'master' $ # ?

git reset

C0 C3 C2 feature master C1

What you want What you have

C0 C3 C2 feature master C1

slide-82
SLIDE 82

DAVID PARSONS - ADVANCED GIT 82

$ git co feature Switched to branch 'feature' $ git (merge | rebase | reset --hard) master ... $ git co master Switched to branch 'master' $ git reset --hard bdfa # ref-to-C0

git reset

C0 C3 C2 feature master C1

What you want What you have

C0 C3 C2 feature master C1

slide-83
SLIDE 83

DAVID PARSONS - ADVANCED GIT 83

$ git co feature Switched to branch 'feature' $ git (merge | rebase | reset --hard) master ... $ git co master Switched to branch 'master' $ git reset --hard bdfa # ref-to-C0 HEAD is now at bdfa5 C0 $

git reset

C0 C3 C2 feature master C1

What you want What you have

C0 C3 C2 feature master C1

slide-84
SLIDE 84

DAVID PARSONS - ADVANCED GIT 84

$ git co feature Switched to branch 'feature' $ git (merge | rebase | reset --hard) master ... $ git co master Switched to branch 'master' $ git reset --hard bdfa5a # ref-to-C0 HEAD is now at bdfa5ab C0 $ git co feature $

git reset

C0 C3 C2 feature master C1

What you want

BINGO !

What you have

C0 C3 C2 feature master C1

slide-85
SLIDE 85

DAVID PARSONS - ADVANCED GIT 85

soft, mixed or hard ?

There are 3 main op(ons to git reset :

Ø

soft, mixed and hard

Here is how to use the main op(ons :

  • -soft

does only 1.

  • -mixed does 1. and 2.
  • -hard goes all the way to 3.

There are also 3 steps that can be done :

  • 1. Move the current branch
  • 2. Update the staging area
  • 3. Update the working directory
slide-86
SLIDE 86

DAVID PARSONS - ADVANCED GIT 86

Cheat sheet

head index work dir wd safe

Commit Level

reset --soft [commit] REF NO NO YES reset [commit] REF YES NO YES reset --hard [commit] REF YES YES NO checkout [commit] HEAD YES YES YES

File Level

reset (commit) [file] NO YES NO YES checkout (commit) [file] NO YES YES NO

slide-87
SLIDE 87

DAVID PARSONS - ADVANCED GIT 87

More undoing …

$ git filter-branch –tree-filter 'rm -f ’ HEAD

git-filter-branch is a very powerful tool

Ø it allows you to apply “filters” on each revision of a branch

This can be useful e.g. when you’ve commited a file that should never have been added (binary file, confiden(al informa(on, …) An alterna(ve to git-filter-branch for “cleansing bad data

  • ut of a git repo” is worth men(oning : BFG Repo-Cleaner.

See : https://rtyley.github.io/bfgrepo-cleaner/

slide-88
SLIDE 88

DAVID PARSONS – ADVANCED GIT 88

Time for Prac1cal Work !

  • Document reference :

hJp://sed.inrialpes.fr/advancedgit-tuto Ø To Do : Sec1on 3

slide-89
SLIDE 89

DAVID PARSONS – ADVANCED GIT 89

Managing remotes

7

slide-90
SLIDE 90

DAVID PARSONS - ADVANCED GIT 90

About remotes

  • Remotes are repositories other than the local one with

which you may want to synchronize.

  • origin is the default name of the default remote
  • Add a remote:

git remote add other git://[...]

  • Fetch remote branches:

git fetch other

  • Push master to remotes/other/master

git push other master

slide-91
SLIDE 91

DAVID PARSONS - ADVANCED GIT 91

Annoying things

  • Delete a remote branch :

git push origin --delete featA

  • Push a tag :

git push origin mytag

  • r

git push --tags

slide-92
SLIDE 92

DAVID PARSONS - ADVANCED GIT 92

Mul(ple remotes, pull-requests

Many projects on GitHub/Lab allow third-party contribu(ons by a mechanism called pull-request. This mechanism can also be used internally for code review. Mul(ple remotes can be very useful in the context of workflows including pull-requests but also in other cases (git annex, migra(ons, …).

slide-93
SLIDE 93

DAVID PARSONS – ADVANCED GIT 93

Other interesting things

8

slide-94
SLIDE 94

DAVID PARSONS - ADVANCED GIT 94

git svn

# Create a file for author mapping echo “dpa = David Parsons <david.parsons@inria.fr>” > authors # Clone an existing svn repo $ git svn clone <url> --authors-file=authors local-git-repo-name $ git svn rebase # gets new revs from svn repo and rebase your work (if any) on top of it # “Push” your changes $ git svn dcommit

Allows to work locally with a git repo and sync it with an svn remote. As a corollary, it allows to migrate from svn to git

Other op(ons of git svn clone I have found useful :

  • -stdlayout if the svn repo follows the trunk/branches/tags layout
  • -ignore-paths / --include-paths
  • -authors-prog
slide-95
SLIDE 95

DAVID PARSONS - ADVANCED GIT 95

git subrepo

# Clone an existing repo as a subrepo (in a subdirectory) $ git subrepo clone <url> <subdir> # Create an embedded git repo $ git subrepo init <subdir> # Pull from upstream $ git subrepo pull <subdir> # Push to upstream $ git subrepo push <subdir>

Alterna(ves :

Ø submodules Ø subtrees

git subrepo allows you to work with embedded git repositories

slide-96
SLIDE 96

DAVID PARSONS - ADVANCED GIT 96

git annex

# Prepare an existing git repo for git annex $ git annex init $ git annex add $ git commit $ # => commits a symlink and stores the file in .git/annex

git annex provides an interes(ng solu(on to version large files.

It basically handles symlinks and provides tools to manage the actual files behind the links.

git annex can be used with a wide variety of types of remote

storage spaces (special remotes). Alterna(ves :

Ø lfs

slide-97
SLIDE 97

DAVID PARSONS - ADVANCED GIT 97

Hooks

Hooks are custom scripts that can be automa(cally triggered when certain important ac(ons occur.

Ø Client-side hooks :

pre-commit, prepare-commit-msg, commit-msg, post-commit, pre-rebase, post-rewrite, post-checkout, post-merge, pre-push, pre-auto-gc

Ø Server-side hooks :

pre-receive, update, post-receive

On plauorms such as forges or GitHubs/Labs, some (many ?) predefined hooks can be set up in a maJer of minutes. Hooks can be used e.g. to send no(fica(ons, run tests prior to commits, enforce any kind of policies, …

slide-98
SLIDE 98

DAVID PARSONS - ADVANCED GIT 98

rerere

One of the most annoying things that a git-user has to do is to resolve conflicts. Even more annoying would be to have to resolve the same conflict several (mes. Sadly, this happens. Mostly when relying heavily on rebase (?)

rerere helps you avoiding this situa(on by reusing recorded resolu(ons .

# Configure rerere functionnality for git git config --global rerere.enabled true

slide-99
SLIDE 99

LIEU LOCALISATION

www.inria.fr

Antenne INRIA Lyon la Doua

www.inria.fr

Thank you

slide-100
SLIDE 100

DAVID PARSONS – ADVANCED GIT 100

Time for Prac1cal Work !

  • Document reference :

hJp://sed.inrialpes.fr/advancedgit-tuto Ø To Do : Sec1on 4