Qualified


Fundamental concepts: revisions, working copy, repository

Solutions for versioning models

  • Lock-Modify-Unlock
  • Copy-Modify-Merge

Repository - is a central store of data. It stores information in the form of a filesystem tree. It like file server with changes history

Working copy - a local reflection of the repositories files and directories. Users then work simultaneously and independently, modifying their private copies. Finally, the private copies are merged together into a new, final version

Revision is a tracked state of project. Every revision in git have it's own sha-1 hash, and can be referenced by it

  • <sha1>, e.g. 'dae86e1950b1277e545cee180551750029cfe735', 'dae86e'
  • <refname>, e.g. 'master', 'heads/master', 'refs/heads/master'

HEAD is synthetic branch, that always points to the currently checked out revision.


Getting (checking out) data from repository

  • init
git init
git add Readme.md
git commit -m 'initial project version'
  • clone
git clone git://github.com/repo/my.git

Examining local changes, comparing working copy to repository

git status

untracked => git add Readme.md

git add Readme.md for indexing

git diff (сравнивает НЕиндексированные изменения с последним коммитом)
git diff --staged (сравнивает индексированные изменения с последним коммитом)
  • git rm - удалить

для отображения изменений


Updating working copy, merging changes

  • git commit -m 'add README.md'

  • git mv Readme.md read.md


Examining change history

  • git log

    • -p разница, внесенная коммитом
    • -2 показать только n последних записи
    • --stat статистика ( 1 files changed, 1 insertions(+), 1 deletions(-))
    • --pretty - форматировать вывод
    • --graph - выводит граф

Отмена изменений

  • git reset --hard HEAD сбрасывает все локальные изменения

  • git checkout -- <file> - сбрасывает внесенные изменения для конкретного файла

  • git revert <commit> создает новый коммит, который откатывает изменения

  • git commit --amend обновляет последний коммит (незапушенный)

  • git reset HEAD benchmarks.rb - сбрасывает индексацию файла (изменения остаются)

  • git blame <file> - показывает кто и когда изменял этот файл

Применение изменений

  • git pull
  • git push
  • git fetch

Discarding changes

Changing Your Last Commit

git commit --amend

This command takes your staging area and uses it for the commit. If you’ve have made no changes since your last commit (for instance, you run this command it immediately after your previous commit), then your snapshot will look exactly the same and all you’ll change is your commit message.

$ git commit -m ’initial commit’
$ git add forgotten_file
$ git commit --amend

All three of these commands end up with a single commit — the second command replaces the results of the first.


Unstaging a Staged File

For example, let’s say you’ve changed two files and want to commit them as two separate changes, but you accidentally type git add * and stage them both. How can you unstage one of the two? to unstage one of files:

git reset HEAD <file>..."

for exmple:

$ git reset HEAD benchmarks.rb
benchmarks.rb: locally modified
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: README.txt
#
# 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: benchmarks.rb
#

The command is a bit strange, but it works. The benchmarks.rb file is modified but once again unstaged.


Unmodifying a Modified File

What if you realize that you don’t want to keep your changes to the benchmarks.rb file? How can you easily unmodify it — revert it back to what it looked like when you last committed (or initially cloned, or however you got it into your working directory)? git checkout -- <file>... to discard changes in working directory

$ git checkout -- benchmarks.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: README.txt
#

You can see that the changes have been reverted. You should also realize that this is a dangerous command: any changes you made to that file are gone — you just copied another file over it. Don’t ever use this command unless you absolutely know that you don’t want the file.


Resolving conflicts in code

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

Git hasn’t automatically created a new merge commit. It has paused the process while you resolve the conflict. If you want to see which files are unmerged at any point after a merge conflict, you can run git status:

[master*]$ git status
index.html: needs merge
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# unmerged: index.html
#

Anything that has merge conflicts and hasn’t been resolved is listed as unmerged. Git adds standard conflict-resolution markers to the files that have conflicts, so you can open them manually and resolve those conflicts. Your file contains a section that looks something like this:

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
53
PRO GIT SCOTT CHACON
</div>
>>>>>>> iss53:index.html

This means the version in HEAD (your master branch, because that was what you had checked out when you ran your merge command) is the top part of that block (everything above the =======), while the version in your iss53 branch looks like everything in the bottom part. In order to resolve the conflict, you have to either choose one side or the other or merge the contents yourself.

$ git mergetool
merge tool candidates: kdiff3 tkdiff xxdiff meld gvimdiff opendiff emerge vimdiff

After all, You can modify that message with details about how you resolved the merge if you think it would be helpful to others looking at this merge in the future — why you did what you did, if it’s not obvious.


Copying, moving files, folders in repository

Git doesn’t explicitly track file movement. If you rename a file in Git, no metadata is stored in Git that tells it you renamed the file. However, Git is pretty smart about figuring that out after the fact — we’ll deal with detecting file movement a bit later. Thus it’s a bit confusing that Git has a mv command. If you want to rename a file in Git, you can run something like

$ git mv file_from file_to

However, this is equivalent to running something like this:

$ mv README.txt README
$ git rm README.txt
$ git add README

Git figures out that it’s a rename implicitly, so it doesn’t matter if you rename a file that way or with the mv command. The only real difference is that mv is one command instead of three — it’s a convenience function. More important, you can use any tool you like to rename a file, and address the add/rm later, before you commit


Committing changes

$ git commit
$ git commit -m "Story 182: Fix benchmarks for speed"

Creating, discovering and breaking locks (if supported)

Git работает по модели Copy-Modify-Merge, потому не использует locks