# Git Objects

There are four types of Git objects: blobs, trees, commits and tags. For each one pygit2 has a type, and all four types inherit from the base `Object` type.

Contents

- Object lookup
- The Object base type
- Blobs
  - Creating blobs
- Trees
  - Tree entries
  - Creating trees
- Commits
  - Signatures
  - Creating commits
- Tags
  - Creating tags

## Object lookup

In the previous chapter we learnt about Object IDs. With an Oid we can ask the repository to get the associated object. To do that the `Repository` class implementes a subset of the mapping interface.

`Repository.``get`(key, default=None)

  Return the Git object for the given id, returns the default value if there’s no object in the repository with that id. The id can be an Oid object, or an hexadecimal string.

  Example:

      >>> from pygit2 import Repository
      >>> repo = Repository('path/to/pygit2')
      >>> obj = repo.get("101715bf37440d32291bde4f58c3142bcf7d8adb")
      >>> obj
      <_pygit2.Commit object at 0x7ff27a6b60f0>

`Repository.``__getitem__`(id)

  Return the Git object for the given id, raise `KeyError` if there’s no object in the repository with that id. The id can be an Oid object, or an hexadecimal string.

`Repository.``__contains__`(id)

  Returns True if there is an object in the Repository with that id, False if there is not. The id can be an Oid object, or an hexadecimal string.

## The Object base type

The Object type is a base type, it is not possible to make instances of it, in any way.

It is the base type of the `Blob`, `Tree`, `Commit` and `Tag` types, so it is possible to check whether a Python value is an Object or not:

    >>> from pygit2 import Object
    >>> commit = repository.revparse_single('HEAD')
    >>> print(isinstance(commit, Object))
    True

All Objects are immutable, they cannot be modified once they are created:

    >>> commit.message = u"foobar"
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: attribute 'message' of '_pygit2.Commit' objects is not writable

Derived types (blobs, trees, etc.) don’t have a constructor, this means they cannot be created with the common idiom:

    >>> from pygit2 import Blob
    >>> blob = Blob("data")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: cannot create '_pygit2.Blob' instances

New objects are created using an specific API we will see later.

This is the common interface for all Git objects:

`Object.``id`

  The object id, an instance of the Oid type.

`Object.``type`

  One of the GIT_OBJ_COMMIT, GIT_OBJ_TREE, GIT_OBJ_BLOB or GIT_OBJ_TAG constants.

`Object.``read_raw`()

  Returns the byte string with the raw contents of the object.

`Object.``peel`(target_type) → Object

  Peel the current object and returns the first object of the given type

## Blobs

A blob is just a raw byte string. They are the Git equivalent to files in a filesytem.

This is their API:

`Blob.``data`

  The contents of the blob, a bytes string. This is the same as Blob.read_raw()

  Example, print the contents of the `.gitignore` file:

      >>> blob = repo["d8022420bf6db02e906175f64f66676df539f2fd"]
      >>> print(blob.data)
      MANIFEST
      build
      dist

`Blob.``size`

  Size.

  Example:

      >>> print(blob.size)
      130

`Blob.``is_binary`

  True if binary data, False if not.

`Blob.``diff`([blob, flag, old_as_path, new_as_path])

  Directly generate a `pygit2.Patch` from the difference between two blobs.

  Returns: Patch.

  Parameters:

  blob : Blob
    The `Blob` to diff.
  flag
    A GIT_DIFF_* constant.
  old_as_path : str
    Treat old blob as if it had this filename.
  new_as_path : str
    Treat new blob as if it had this filename.

`Blob.``diff_to_buffer`([buffer, flag, old_as_path, buffer_as_path])

  Directly generate a `Patch` from the difference between a blob and a buffer.

  Returns: Patch.

  Parameters:

  buffer : Blob
    Raw data for new side of diff.
  flag
    A GIT_DIFF_* constant.
  old_as_path : str
    Treat old blob as if it had this filename.
  buffer_as_path : str
    Treat buffer as if it had this filename.

### Creating blobs

There are a number of methods in the repository to create new blobs, and add them to the Git object database:

`Repository.``create_blob`(data) → Oid

  Create a new blob from a bytes string. The blob is added to the Git object database. Returns the oid of the blob.

  Example:

      >>> id  = repo.create_blob('foo bar')   # Creates blob from bytes string
      >>> blob = repo[id]
      >>> blob.data
      'foo bar'

`Repository.``create_blob_fromworkdir`(path) → Oid

  Create a new blob from a file within the working directory. The given path must be relative to the working directory, if it is not an error is raised.

`Repository.``create_blob_fromdisk`(path) → Oid

  Create a new blob from a file anywhere (no working directory check).

`Repository.``create_blob_fromiobase`(io.IOBase) → Oid

  Create a new blob from an IOBase object.

There are also some functions to calculate the id for a byte string without creating the blob object:

`pygit2.``hash`(data) → Oid

  Returns the oid of a new blob from a string without actually writing to the odb.

`pygit2.``hashfile`(path) → Oid

  Returns the oid of a new blob from a file path without actually writing to the odb.

## Trees

A tree is a sorted collection of tree entries. It is similar to a folder or directory in a file system. Each entry points to another tree or a blob. A tree can be iterated, and partially implements the sequence and mapping interfaces.

`Tree.``__getitem__`(name)

  Return the TreeEntry object for the given name. Raise `KeyError` if there is not a tree entry with that name.

`Tree.``__contains__`(name)

  Return True if there is a tree entry with the given name, False otherwise.

`Tree.``__len__`()

  Return the number of entries in the tree.

`Tree.``__iter__`()

  Return an iterator over the entries of the tree.

`Tree.``diff_to_tree`([tree, flags, context_lines, interhunk_lines, swap]) → Diff

  Show the changes between two trees.

  Parameters:

  tree: `Tree`
    The tree to diff. If no tree is given the empty tree will be used instead.
  flag
    A GIT_DIFF_* constant.
  context_lines
    The number of unchanged lines that define the boundary of a hunk (and to display before and after).
  interhunk_lines
    The maximum number of unchanged lines between hunk boundaries before the hunks will be merged into a one.
  swap
    Instead of diffing a to b. Diff b to a.

`Tree.``diff_to_workdir`([flags, context_lines, interhunk_lines]) → Diff

  Show the changes between the `Tree` and the workdir.

  Parameters:

  flag
    A GIT_DIFF_* constant.
  context_lines
    The number of unchanged lines that define the boundary of a hunk (and to display before and after).
  interhunk_lines
    The maximum number of unchanged lines between hunk boundaries before the hunks will be merged into a one.

`Tree.``diff_to_index`(index[, flags, context_lines, interhunk_lines]) → Diff

  Show the changes between the index and a given `Tree`.

  Parameters:

  tree : `Tree`
    The tree to diff.
  flag
    A GIT_DIFF_* constant.
  context_lines
    The number of unchanged lines that define the boundary of a hunk (and to display before and after).
  interhunk_lines
    The maximum number of unchanged lines between hunk boundaries before the hunks will be merged into a one.

### Tree entries

`TreeEntry.``name`

  Name.

`TreeEntry.``id`

  Object id.

`TreeEntry.``hex`

  Hex oid.

`TreeEntry.``filemode`

  Filemode.

`TreeEntry.``type`

  Type.

`TreeEntry.``__cmp__`(TreeEntry)

  Rich comparison between tree entries.

Example:

    >>> tree = commit.tree
    >>> len(tree)                        # Number of entries
    6

    >>> for entry in tree:               # Iteration
    ...     print(entry.id, entry.type, entry.name)
    ...
    7151ca7cd3e59f3eab19c485cfbf3cb30928d7fa blob .gitignore
    c36f4cf1e38ec1bb9d9ad146ed572b89ecfc9f18 blob COPYING
    32b30b90b062f66957d6790c3c155c289c34424e blob README.md
    c87dae4094b3a6d10e08bc6c5ef1f55a7e448659 blob pygit2.c
    85a67270a49ef16cdd3d328f06a3e4b459f09b27 blob setup.py
    3d8985bbec338eb4d47c5b01b863ee89d044bd53 tree test

    >>> entry = tree['pygit2.c']         # Get an entry by name
    >>> entry
    <pygit2.TreeEntry object at 0xcc10f0>

    >>> blob = repo[entry.id]           # Get the object the entry points to
    >>> blob
    <pygit2.Blob object at 0xcc12d0>

### Creating trees

`Repository.``TreeBuilder`([tree]) → TreeBuilder

  Create a TreeBuilder object for this repository.

`TreeBuilder.``insert`(name, oid, attr)

  Insert or replace an entry in the treebuilder.

  Parameters:

  attr
    Available values are GIT_FILEMODE_BLOB, GIT_FILEMODE_BLOB_EXECUTABLE, GIT_FILEMODE_TREE, GIT_FILEMODE_LINK and GIT_FILEMODE_COMMIT.

`TreeBuilder.``remove`(name)

  Remove an entry from the builder.

`TreeBuilder.``clear`()

  Clear all the entries in the builder.

`TreeBuilder.``write`() → Oid

  Write the tree to the given repository.

`TreeBuilder.``get`(name) → TreeEntry

  Return the TreeEntry for the given name, or None if there is not.

## Commits

A commit is a snapshot of the working dir with meta informations like author, committer and others.

`Commit.``author`

  The author of the commit.

`Commit.``committer`

  The committer of the commit.

`Commit.``message`

  The commit message, a text string.

`Commit.``message_encoding`

  Message encoding.

`Commit.``raw_message`

  Message (bytes).

`Commit.``tree`

  The tree object attached to the commit.

`Commit.``tree_id`

  The id of the tree attached to the commit.

`Commit.``parents`

  The list of parent commits.

`Commit.``parent_ids`

  The list of parent commits’ ids.

`Commit.``commit_time`

  Commit time.

`Commit.``commit_time_offset`

  Commit time offset.

### Signatures

The author and committer attributes of commit objects are `Signature` objects:

    >>> commit.author
    <pygit2.Signature object at 0x7f75e9b1f5f8>

`Signature.``name`

  Name.

`Signature.``raw_name`

  Name (bytes).

`Signature.``email`

  Email address.

`Signature.``raw_email`

  Email (bytes).

`Signature.``time`

  Unix time.

`Signature.``offset`

  Offset from UTC in minutes.

### Creating commits

`Repository.``create_commit`(reference_name, author, committer, message, tree, parents[, encoding]) → Oid

  Create a new commit object, return its oid.

Commits can be created by calling the `create_commit` method of the repository with the following parameters:

    >>> author = Signature('Alice Author', 'alice@authors.tld')
    >>> committer = Signature('Cecil Committer', 'cecil@committers.tld')
    >>> tree = repo.TreeBuilder().write()
    >>> repo.create_commit(
    ... 'refs/heads/master', # the name of the reference to update
    ... author, committer, 'one line commit message\n\ndetailed commit message',
    ... tree, # binary string representing the tree object ID
    ... [] # list of binary strings representing parents of the new commit
    ... )
    '#\xe4<u\xfe\xd6\x17\xa0\xe6\xa2\x8b\xb6\xdc35$\xcf-\x8b~'

## Tags

A tag is a static label for a commit. See references for more information.

`Tag.``name`

  Tag name.

`Tag.``target`

  Tagged object.

`Tag.``tagger`

  Tagger.

`Tag.``message`

  Tag message.

`Tag.``get_object`() → object

  Retrieves the object the current tag is pointing to.

### Creating tags

`Repository.``create_tag`(name, oid, type, tagger, message) → Oid

  Create a new tag object, return its oid.