Catalyst – Git



Catalyst – Git

1 0


git-basic

The intro slides for the basic git course

On Github catalyst-training / git-basic

Catalyst

Git

Revision control for humans # Make sure the server has a working SSH daemon running # Set up shared git repo mkdir /tmp/test3.git cd /tmp/test3.git git init --bare cd /tmp git clone /tmp/test3.git /tmp/work cd /tmp/work echo 'evanwashere' > evan.txt git add evan.txt git commit -m 'initial commit - one file' git push origin master

Administrivia

  • Bathrooms.
  • Drinks.
  • Fire exits.
  • Please interupt to ask questions.

Introduction

  • Slides: http://catalyst-training.github.io//git-basic/
  • The format of this course is mostly a tutorial (with some lecturing thrown in)
  • The tutorial is based on the commandline
  • The tutorial is designed to uncover the concepts
  • Not necessarily to provide all the command syntaxHopefully if you are armed with the concepts, the internet will help you find the specifics you need

Why use revision control software?

You (should) want it if...

  • You want to review what you have just changed
  • You want to go back to a previous safe point
  • You want to look at how something used to be
  • You want to know why something changed
  • You are sick of keeping *.bak files

Why use revision control software?

You need it if...

  • You are working with other people who use it
  • You want to maintain multiple versions of the same thing
  • You need to coordinate changes accross multiple files

What does revision control provide?

  • Track changes (to almost anything)
  • View history
  • Look back to find when bugs were created
  • Find the reasoning behind why something is how it is
  • Roll back changes
  • Apply kudos for effort
  • Backups of your important stuff

What options are there?

  • RCS
  • CVS
  • Subversion
  • Darcs
  • Perforce
  • Bzr
  • ...

Why should you use Git?

  • It is fast
  • Working with branches makes sense
  • You can do meaningful work without a network connection
  • It does not dictate your workflow
  • It protects your data
  • Once you master the concepts, you can do some really creative (and useful!) stuff
  • The cool kids use it

Installing

# Required
$ sudo aptitude install git
# Recommended
$ sudo aptitude install gitk git-gui
# FYI...
$ sudo aptitude search git
Pause here to explain the way we are showing commands * talk about '$' as the prompt, etc

Installing (alternative OS)

Create a new repository

git init

$ mkdir /tmp/test
$ cd /tmp/test
$ git init
Initialized empty Git repository in .git/

Check the status with git status

$ git status
# On branch master
#
# Initial commit
#
nothing to commit (create/copy files and use "git add" to track)

What did that do?

Git is just a bit different from other revision control systems

The 'staging area' is often called the 'index'

Getting help

# git help COMMAND
$ git help status

# man git-COMMAND
$ man git-status
The COMMANDs we have used so far are 'init' and 'status', so....

Global configuration settings

Before we start...

# We need to tell git who you are - But it's OK to lie....
$ git config --global user.name "Jed I. Night"
$ git config --global user.email "null@catalyst.net.nz"
# You can choose an editor.... (this is not your IDE)
$ git config --global core.editor gedit
$ git config --global core.editor wordpad
# If you will be working on windows, but need to deal with unix
$ git config --global core.autocrlf true
Is anyone using windows? you can't use gedit, and you don't want to use notepad, try: - notepad++ - wordpad - ANYTHING else! - but only within the current repository (which is /tmp/test)

Project configuration settings

This will tell Git you like to see pretty colours on the screen

$ git config color.ui auto
These settings will override the global settings - but only within the current repository (which is /tmp/test)

Accessing the configuration settings

Global data is stored in ~/.gitconfig

Project data is stored in /tmp/test/.git/config

# Use `git config` to see it
$ git config -l
# ..or just edit the files
$ gedit ~/.gitconfig /tmp/test/.git/config

Managing Files

Make some changes...

$ touch myscript.pl
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    myscript.pl
nothing added to commit but untracked files present (use "git add" to track)

Tell Git to track those files

git add

$ git add myscript.pl
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#    new file: myscript.pl
#
This actually adds the file to the 'index'

Change an existing file

Make some changes...

$ echo DATA > myscript.pl
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#    new file:   myscript.pl
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#    modified:   myscript.pl
#
This is our first clue that Git tracks changes rather than files

See what you have done

git diff

$ git diff
--- a/myscript.pl
+++ b/myscript.pl
@@ -0,0 +1 @@
+DATA

Change an existing file

We need to tell Git that you intend to commit the checked out version, with git add

$ git add myscript.pl
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#    new file:   myscript.pl
#

Committing changes

Commit your work with git commit

# You will be stuck in an editor so you can input a commit message.
$ git commit myscript.pl
Created commit ae54011: Add a message.
1 files changed, 3 insertions(+), 0 deletions(-)
create mode 100644 myscript.pl

Normally, you WILL make your commit message meaningful!

Check if everyone got a reasonable editor! Windows problems can be resolved by looking at https://github.com/catalyst-training/git-basic/wiki/Windows-editor

Committing changes - some options

You don't have to git add all your changes manually

# Add <file>, and then commit
$ git commit <file>
# Add all your changes, and then commit
$ git commit -a
# You can choose different editor for this commit...
$ EDITOR=vim git commit -a
# You don't have to use an editor at all...
$ git commit -m 'commit message goes here'

Managing Files - Permissions

Oops, that file isn't executable

$ chmod 755 myscript.pl
$ git commit myscript.pl
Created commit 378af93: Make it executable.
0 files changed, 0 insertions(+), 0 deletions(-)
mode change 100644 => 100755 myscript.pl

Managing Files - Move

To rename a file use git mv

$ git mv myscript.pl README.txt
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    renamed: myscript.pl -> README.txt
#
# This has changed our checkout, and the index
# so we are ready to commit the change
$ git commit
Created commit fabd446: Rename the file.
1 files changed, 0 insertions(+), 0 deletions(-)
rename myscript.pl => README.txt (100%)

Managing Files - Delete

To delete a file use git rm

# This won't actually work, because we haven't
# created "another-script.pl"
# ... but you can try it, if you like....
$ git rm -f another-script.pl
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    deleted: another-script.pl
#

And commit the change

$ git commit
Created commit bd10c5f: Remove another-script.pl
0 files changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 another-script.pl

Managing Files - ignore them

# Let's imagine your editor keeps creating '.swp' files
$ touch README.txt.swp
$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       README.txt.swp

Managing Files - ignore them

# Add a line that conatins '*.swp'
$ gedit .gitignore
$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       .gitignore
# We can then commit the .gitignore file
$ git add .gitignore
$ git commit -m 'Created a .gitignore file'
You can put a different .gitignore file in each directory ...or stick to one in the root of your project

Ignoring files Privately vs. Publicly

  • Adding things to .gitignore makes it part of your project...
  • Instead you can ignore things using .git/info/exclude.

Tags

Tags allow you to mark specific points in history as being important.

Often people use this functionality to mark release points.

They work pretty much like you would expect...

$ git tag v1.0
$ git tag v1.0-production -m 'this might be important later!'
$ git tag
$ git show v1.0
$ git show v1.0-production
2 types of tags: lightweight and annotated Tags don't get shared, by default. Also, explain that you can git show anything (tag, branch, sha1, etc).

Change Logs

Use git log

$ git log
commit 09f90bc2a74f7ca2f825c4a386e168649b9fec97
Author: Evan Giles 
Date:   Thu Dec 16 11:53:48 2010 +1300

    Rename the file.

commit f7123c5ffdccbed11b50b0b74a181186e1a13028
Author: Evan Giles 
Date:   Thu Dec 16 11:53:25 2010 +1300

    Make it executable

commit 8657bea3230587abdcbe39e6bf699c9ee8f505a6
Author: Evan Giles 
Date:   Thu Dec 16 11:52:51 2010 +1300

    Add a message.

By default the output is piped into $PAGER

Change Logs

# You can change the output format
$ git log --prety=onleline
# Or specify which file or directory you are interested in
$ git log README.txt
# There are lots of options..
$ git log --pretty=oneline --since='5 minutes ago' --graph

Change Logs - Annotate

Show who made changes to what line

$ git annotate filename.pl
b61863c8  (Andrew R. 2008-05-09 17:01:41 +1200 1) #!/usr/bin/perl -w
b61863c8  (Andrew R. 2008-05-09 17:01:41 +1200 2)
b61863c8  (Andrew R. 2008-05-09 17:01:41 +1200 3) print "silly script\n";
9c08faf4  (Bad Coder 2008-05-09 17:18:18 +1200 4) I'm in ur code, breaking ur stuff.

Who is this Bad Coder?

# Better remembered as `git blame`
$ git blame filename.pl
b61863c8 (Andrew R.   2008-05-09 17:01:41 +1200 1) #!/usr/bin/perl -w
b61863c8 (Andrew R.   2008-05-09 17:01:41 +1200 2)
b61863c8 (Andrew R.   2008-05-09 17:01:41 +1200 3) print "silly script\n";
9c08faf4 (Bad Coder   2008-05-09 17:18:18 +1200 4) I'm in ur code, breaking ur stuff.

Change logs - GUI

Not strictly change logs, but... gitk / qgit / gitg / etc

Some more concepts - commits

  • It is important to understand that git thinks in commits
  • Each commit refers to a previous commit (its parent)
  • Commits can be referenced by their SHA1 checksum
    • or an abbreviation of it
    • or by a number of things that might refer to them
  • gitk lets you visualise the commit history, which helps a lot

Commits are....

Totally unchangeable This means that once you have committed your work, it is really safe

Branching - List

To show branches use git branch

$ git branch
* master

Only one branch, called master

The '*' indicates that it is your current branch

You can also use 'git status'

Branching - Create

Use git branch (or git checkout -b)

$ git checkout -b new-branch
Switched to a new branch "new-branch"

Will create "new-branch", and check it out for you

$ git branch
  master
* new-branch
mention that 'git checkout' is a convenience interface ...it does several things in one step

Branching - Create somewhere else

By default a new branch will be created at the commit you already have checked out

You can also create a new branch at another commit

$ git checkout -b another-branch master
Switched to a new branch "another-branch"
$ git branch
* another-branch
  master
  new-branch
Here, the checkout command is actually doing 3 things - go the the master branch - make a branch there (callled 'another-branch') - checkout the 'another-branch' branch

Branching - Change Branch

Use git checkout

$ git checkout new-branch
Switched to branch "new-branch"
$ git branch
  another-branch
  master
* new-branch
Don't forget to see how this is shown in gitk

Branching - What's the deal?

# Make a change to a file (and commit that change)
$ echo "... From new-branch" >> README.txt
$ git commit README.txt
Created commit a6ed2cf: From new-branch
1 files changed, 1 insertions(+), 0 deletions(-)
# Check the file..
$ cat README.txt
DATA
... From new-branch
# Switch to a different branch (master)
$ git checkout master
Switched to branch "master"
# The text we added ain't there
$ cat README.txt
DATA

Branching - Why?

  • Many (most) projects have a branch for each release
  • Branches are useful for experimental features / refactoring
  • Branches happen (without even trying) when several people try to work on the same project - but I'll explain that soon ;)
It is useful to think of branches as an 'alternative reality'

Merging - Simple Case

You should now be on the master branch

$ git status
# On branch master
nothing to commit (working directory clean)

Use git merge

$ git merge new-branch
Updating e766bfb..a6ed2cf
Fast forward
README.txt |    1 +
1 files changed, 1 insertions(+), 0 deletions(-)

If there are no conflicts, this may make a new commit object

but in this case, we have done a fast forward merge

- We are merging changes IN, from somewhere else - explain the fast forward bit - talk about merges being line by line, so not for binary data - use gitk to see what happened

Merging - get ready for a conflict

Conflicts are more difficult (lets create one)

# Make a change to a file, commit that change to 'master'
$ echo "New value for data" > README.txt
$ git commit -a -m 'update script with a new value'

# Change branches, make a change, and commit
$ git checkout new-branch
$ echo "different value for data" > README.txt
$ git commit -a -m 'update script with a different value'

# Go back to the master branch, if we try to merge - there
# will be a problem!
$ git checkout master

Merging - you can't do that

If there is a conflict then git will stop and make you fix it.

$ git merge new-branch
Auto-merged README.txt
CONFLICT (content): Merge conflict in README.txt
Automatic merge failed; fix conflicts and then commit the result.
$ git status
# On branch master
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      README.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
$ cat README.txt
<<<<<<< HEAD:README.txt
New value for data
=======
different value for data
>>>>>>> new-branch:README.txt
Mention git merge --abort

Merging - Fixing conflicts

Lots of tools to help fix things up. Hand edit, xxdiff, smartmerge, etc

We'll just fix it by editing the file

$ gedit README.txt
$ cat README.txt
New, different value for data

But Git still won't allow us to continue...

$ git commit
U    README.txt
fatal: 'commit' is not possible because you have unmerged files.
Please, fix them up in the work tree, and then use 'git add/rm <file>' as
appropriate to mark resolution and make a commit, or use 'git commit -a'.

Merging - Success at last

We need to tell Git that it has been fixed before we commit

$ git add README.txt
$ git commit
Created commit a411f2a: Merge branch 'new-branch'

In this case the commit message is automatically created, but you can edit it if you want.

Merge branch 'new-branch'

Conflicts:

    README.txt

Merging - How does it look?

Looking at the trees in gitk helps you understand stuff.

$ gitk

Where are we?

Where are we going?

What is the opposite of push? (it's not pull!) Recommend "git fetch; git merge" in place of "git pull"

Creating Repositories - Revisited

We already know how to create a new repositry

$ git init
Initialized empty Git repository in .git/

...but normally, you want to join in with an existing project

Clone an existing repository

In practise, you're more likely to use git clone.

To check out the source code of a random project:

$ cd /tmp
$ git clone https://github.com/catalyst-training/git-basic
Cloning into git-basic...
remote: Counting objects: 90, done.
remote: Compressing objects: 100% (43/43), done.
remote: Total 90 (delta 44), reused 90 (delta 44)
Receiving objects: 100% (90/90), 31.62 KiB, done.
Resolving deltas: 100% (44/44), done.
$ cd git-basic
$ ls
$ gitk
git remote -v

Remote repositories - URLs

# Clone an existing repository via HTTP
$ git clone https://github.com/catalyst-training/git-basic
# Clone an existing repository via SSH
$ git clone ssh://git.catalyst.net.nz/git/public/git.git
# Clone an existing local repository (this is only slightly mad)
$ git clone test test2

Terminology: Remote branches

Remote branches are references (pointers) to the state of branches in your remote repositories.

They're local branches that you can't move; they're moved automatically for you whenever you do any network communication.

Remote branches act as bookmarks to remind you where the branches on your remote repositories were the last time you connected to them.

Terminology: Origin

You can see all branches (including the remote ones) with the git branch command

$ cd /tmp/git-basic/
$ git branch -a
* master
  remotes/origin/master
you don't need to type 'remotes' to refer to these branches

Other remotes

You can manipulate your view of other repositories with the git remote command

$ git remote add duplicate https://github.com/catalyst-training/git-basic
$ git remote show
duplicate
origin
$ git fetch --all
Fetching origin
Fetching duplicate
From https://github.com/catalyst-training/git-basic
 * [new branch]      gh-pages   -> duplicate/gh-pages
 * [new branch]      master     -> duplicate/master
origin is not special, except that: - it is created by default when you clone a repository - some commands (like fetch) assume you mean origin if you don't specify the remote - etc, etc

Git is distributed... (1)

Corporate Workflow

You will probably use this

Git is distributed... (2)

Integration manager Workflow

A quick diversion: http://www.github.com

Git is distributed... (3)

Dictator Workflow

This is how the Linux kernel is managed

Git is distributed... (4)

Peer to peer Workflow

Ways to work with Git (Git Flow)

http://nvie.com/posts/a-successful-git-branching-model/

- It seems excessive, but it's not a waste of time - origin/master represents prod-ready - develop is generally where things begin - hotfixes, releases, features - merge with '--no-ff' - branches get deleted when you are finished with them - Use of pull requests in stash makes code review, merging easy

Once upon a time....

Alice and Bob wanted to do some work

So they both made some changes....

Alice pushes her changes...

But Bob has a problem...

Now Bob needs to fetch the changes from Alice

and merge them with his work

They all lived happily ever after...

Now we can try it out

# Clone a new repository
$ cd /tmp
$ git clone https://github.com/git-training-open/alice1.git
$ cd /tmp/alice1
# Create a new file (and commit)
$ gedit $YOURNAME.txt
$ git add $YOURNAME.txt
$ git commit
# Push your changes to the shared repository
# git-training-open / openup1
$ git push origin master
# You are now Bob!
$ git fetch
$ git merge origin/master
Explain What is going on with "origin" and "master" here: - git push origin master - git merge origin/master Also introduce the idea that commands have defaults: - git push ... git push origin master - - -

Changing your commits

You can 'change' the most recent commit using git commit

$ git add something.txt
$ git commit --amend

This is quite a big deal...

Will someone please pull me up on this?! Explain how this works - That you are not changing anything here - just making a new commit which is quite like the old one - and then moving the labels around Warning: - Do not change commits that exist outside your repository. - If you do, people will hate you, and you'll be scorned by friends and family.

Copy a commit

You can copy a commit from one branch to another

You might want to do this if, for example, a bug is discovered on your development branch that also needs to be applied to your production branch.

$ git cherry-pick e43a6fd3e94888d76779ad79fb568ed180e5fcdf
The commit created will look the same, but have a different commit id Note that the cherry-pick can fail, if there are conflicts

Undo a commit

You can undo a previous commit with git revert.

This makes a new commit, that is the exact opposite of a previous commit in your repository.

The previous commit remains intact.

$ git revert e43a6fd3e94888d76779ad79fb568ed180e5fcdf
$ git log --pretty=oneline
830d77273fc24c0708403102a05a5a5ffecfce93 Revert "Introduce bug"
d7a1ee454168081227ee82c5f11bb08f77e2643d Unrelated change
e43a6fd3e94888d76779ad79fb568ed180e5fcdf Introduce bug
When you revert the commit, you get dropped into an editor in case you want to can edit the commit message..

Getting serious with copying commits

As an alternative to merging, you can use git rebase.

Instead of making a new commit which joins two branches together, it copies your changes on top of the other branch...

You use it just like a merge.

$ git rebase origin/master
Draw what this does, contrast it with a merge

Rebase vs. Merge

One point of view on this is that your repository's commit history is a record of what actually happened. It's a historical document, valuable in its own right, and shouldn't be tampered with. From this angle, changing the commit history is almost blasphemous; you're lying about what actually transpired. So what if there was a messy series of merge commits? That's how it happened, and the repository should preserve that for posterity.

History is an audit trail

Rebase vs. Merge

The opposing point of view is that the commit history is the story of how your project was made. You wouldn't publish the first draft of a book, and the manual for how to maintain your software deserves careful editing. This is the camp that uses tools like rebase and filter-branch to tell the story in the way that's best for future readers.

History is a story You should not change commits that exist outside your repository

A more advanced rebase

$ git rebase --interactive origin/master
pick a3895fe Try a bit harder to return a useful value from all methods
pick 180e665 Release engineering (0.8)
pick 2a6d832 Update Build.PL for newer build tools
pick e1fac16 Use semantic versioning (http://semver.org/)

# Rebase aa8a695..e1fac16 onto aa8a695
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

Loose ends...

git reset

In it's simplest form, it allows you to throw away changes you have made locally.

$ git status
# On branch 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:   index.html
$ git reset --hard
HEAD is now at 5cc4a26 wr235825: small changes
$ git status
# On branch master
nothing to commit (working directory clean)

Loose ends...

git reset

# You can also change to a different commit before doing
# the reset
$ git reset --hard HEAD^^
HEAD is now at a51452d rewrite the 'begin' function
# This changes your commit, but leaves your files and index untouched
# - changes that you have 'added' are still ready to commit
# - changes to files are still ready to add
$ git reset --soft HEAD^^
# This changes your commit and the index, but leaves your files untouched
# - changes to files are now ready to add, even if you had already added them
$ git reset --mixed HEAD^^

Loose ends...

git stash (hide)

You can hide your changes away for later use

$ git status
# On branch master
#
#    modified:   myscript.pl

$ git stash
Saved working directory and index state WIP on master: 5cc4a26 added a file
$ git status
# On branch master
nothing to commit (working directory clean)

Loose ends...

git stash (restore)

Later on, you can restore your changes

$ git status
# On branch master
nothing to commit (working directory clean)

$ git stash pop
# On branch 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:   myscript.pl
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (1a69a03f554a61ea50b3a9e2eb1182608cb50c8e)
You can manage multiple stashes if you want....but that gets confusing :(

Graphical interfaces

A live demo!

  • Changes with gitk
  • Using git gui
Demonstrate how to: - gitk: change branches - gitk: reset - gitk: making a tag - gitk: integration with git-gui - git gui: making a commit - git gui: amend a commit -

The End

Questions?

The presentation content is licensed under a Creative Commons Attribution 3.0 License. (http://creativecommons.org/licenses/by/3.0)The presentation display is licensed seperately by Hakim El Hattab / @hakimel
Thing to discuss to fill in time - git add/commit -p - git reflog - git bisect - -

Problem 1

Fix a production bug

We have just discovered that there is a program in production that is not executable - the site is down!

But we can't deploy the latest code because it's not ready...

Please find the release tag 'release-1-0' in the repository 'https://github.com/catalyst-training/example1.git', and fix the bug!

Note that these problems are NOT a test - you haven't been given enough information yet It is just some everyday problems that we can work through together...

Problem 1

Solution

# Clone the repository
$ cd /tmp
$ git clone https://github.com/catalyst-training/example1.git
$ cd /tmp/example1

# Make a new branch (at the point we want to change)
$ git checkout -b release-1 release-1-0

# Fix the problem
$ chmod +x program
$ git commit -a -m 'make the program executable'
$ # git push origin release-1
Discuss The fact that we can't push to that URL And even if we could, we can't push to the master branch * What would we normally do next (cherry-pick / merge), probably not rebase

Problem 2

Change the past

I have just noticed that https://github.com/catalyst-training/example2.git has a dodgey commit. The commit message is 'Oooh, this smells a bit funny...'.

Please make it go away

Once again, you won't be able to push your changes - but that's ok.

Problem 2

Solution

# Clone the repository
$ cd /tmp
$ git clone https://github.com/catalyst-training/example2.git
$ cd /tmp/example2
# Work out what we want to do
$ git log --oneline
5c90449 Remove the README file
3bec061 Some more stuff
3114205 Oooh, this smells a bit funny...
510043a Another list - snakes
6a624b3 Add a list of lists
# Rewrite the past
$ git rebase --interactive 510043a

Problem 2b

Change the past, more!

Wow, now that I see what you can do to tidy up the past, I realise I want more

Please add your favourite movie to the list of movies - but make it look like it was added with all the other movies.

Once again, you won't be able to push your changes - but that's ok.

Problem 2b

Solution

$ git log --oneline
# This will be more complex, from within this command you'll need to:
#   $ echo '* Highlander II' >> lists/movies.txt
#   $ git add lists/movies.txt
#   $ git commit --amend
#   $ git rebase --continue
$ git rebase --interactive b9fb9c8

Problem 3

Join 2 repositories together

We have been working as two teams for a while now, and we have realised that the two teams are so interlinked that we should be all working from the same repository,

Please join https://github.com/catalyst-training/example1.git and https://github.com/catalyst-training/example2.git together!

Of course, I would like to keep all files and history from both teams intact.

This is a true story

Problem 3

Solution

$ cd /tmp/example2

# Add another remote!
$ git remote add ex1 https://github.com/catalyst-training/example1.git

# Fetch the commits from example1 into this repo
$ git fetch ex1

# Merge ex1/master into origin/master
$ git merge ex1/master
$ # git push origin master
Discuss If there were conflicts, we could resolve them, or put the projects into subdirs first We could have used the directory /tmp/example1/.git as the URL for ex1 - that would have allowed us to include our bugfix into the merge * We still could!, and we could then cherry-pick our bugfix in!

Problem 4

Github

Please create a github account, then 'fork' the repository 'https://github.com/catalyst-training/example3'

Then make a change, and create a pull request so I can accept your work.

You can do the whole thing in your browser!

This will take a bit more time, help with - Github account - SSH keys - fork vs clone - editing inside the browser - pull requests - etc...

Problem 4b

Git Gui

That was great, but now lets try again, using git-gui to make and push your commit.

I'll get you started...

$ cd /tmp
$ git clone https://github.com/YOURNAME/example3.git
$ cd /tmp/example3
$ echo 'Sean Connery' > $YOURNAME.txt
$ git gui

Problem 5

Mess with a remote branch

Using your github account, push a 'password' to github.

$ echo 'butter' > password.txt
$ git add password.txt
$ git commit -m "I may regret this...."
$ git push origin master

Now make it go away.

There are several ways to do this, but is it really gone?

Problem 5

Solution

# Amend the commit and force push
$ echo '' > password.txt
$ git commit -am "Nothing to see here..."
$ git push -f origin master
# Rewind and force push
$ git reset --hard HEAD^
$ git push -f origin master
# Delete the remote branch and push a new one
$ git push origin :master
$ git reset --hard HEAD^
$ git push origin master
Note the odd syntax for deleting a branch!

Problem 6

Abort a merge

Go to your 'example2' project, and try to merge in the 'kittens' branch...

# Create a conflict
$ cd /tmp/example2
$ git merge origin/kittens
$ git status

Oh, no, there are conflicts! Get me out of here!

or a rebase ...

Problem 6

Solution

# Too hard, I'll try again some other time
$ git merge --abort

Problem 6b

Use tools to try to resolve a conflict

Go to your 'example2' project, and try to merge in the 'kittens' branch...

# Create a conflict
$ cd /tmp/example2
$ git merge origin/kittens
$ git status

There are conflicts, but I think you can handle them!

Problem 6b

Solution

# Let's give it a go...
$ git mergetool
Also, we should try this again after installing 'meld'

Problem 7

Throw away your changes

What if you make some changes, and you want to get back to safety?

$ cd /tmp/example2
$ echo 'A dragon will fix it' > lists/links.txt
$ rm lists/movies.txt
$ git status

Problem 7

Solution

$ git reset --hard
Could we use git-reset? git-checkout? gitk? git-clean?

The End

That's really it this time

Extra things to discuss, to fill in time: - Setting up a bare repo - git add/commit -p - git bisect - git reflog

open source technologists

Catalyst Git Revision control for humans # Make sure the server has a working SSH daemon running # Set up shared git repo mkdir /tmp/test3.git cd /tmp/test3.git git init --bare cd /tmp git clone /tmp/test3.git /tmp/work cd /tmp/work echo 'evanwashere' > evan.txt git add evan.txt git commit -m 'initial commit - one file' git push origin master