From 4748e813980e1316aa364e0830a4dc082ff86eb0 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 3 Nov 2009 21:43:17 +0100 Subject: added all new files to reference.rst and corrected the worst mistakes. There are still a few errors left that I cannot fix as it complains about whitespace in the end ... that is exactly what I hate restructured text for, its just a ... anyway. --- doc/reference.rst | 84 +++++++++++++++++++++++++++++++++++++------------------ lib/git/index.py | 9 +++--- lib/git/refs.py | 5 ++-- lib/git/remote.py | 21 +++++++------- 4 files changed, 75 insertions(+), 44 deletions(-) diff --git a/doc/reference.rst b/doc/reference.rst index 078cbdf6..9cc32b71 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -10,27 +10,63 @@ Actor :members: :undoc-members: -Blob ----- +Objects.Base +------------ + +.. automodule:: git.objects.base + :members: + :undoc-members: + +Objects.Blob +------------ -.. automodule:: git.blob +.. automodule:: git.objects.blob :members: :undoc-members: + +Objects.Commit +-------------- -Git ---- +.. automodule:: git.objects.commit + :members: + :undoc-members: + +Objects.Tag +----------- -.. automodule:: git.cmd +.. automodule:: git.objects.tag :members: :undoc-members: -Commit +Objects.Tree +------------ + +.. automodule:: git.objects.tree + :members: + :undoc-members: + +Objects.Utils +------------- + +.. automodule:: git.objects.utils + :members: + :undoc-members: + +GitCmd ------ -.. automodule:: git.commit +.. automodule:: git.cmd :members: :undoc-members: + +Config +------ + +.. automodule:: git.config + :members: + :undoc-members: + Diff ---- @@ -45,17 +81,25 @@ Errors :members: :undoc-members: -Head +Index +------ + +.. automodule:: git.index + :members: + :undoc-members: + + +Refs ---- -.. automodule:: git.head +.. automodule:: git.refs :members: :undoc-members: -Lazy ----- +Remote +------ -.. automodule:: git.lazy +.. automodule:: git.remote :members: :undoc-members: @@ -73,20 +117,6 @@ Stats :members: :undoc-members: -Tag ---- - -.. automodule:: git.tag - :members: - :undoc-members: - -Tree ----- - -.. automodule:: git.tree - :members: - :undoc-members: - Utils ----- diff --git a/lib/git/index.py b/lib/git/index.py index 705b1ae7..e368f531 100644 --- a/lib/git/index.py +++ b/lib/git/index.py @@ -44,11 +44,12 @@ class _TemporaryFileSwap(object): class BaseIndexEntry(tuple): """ - Small Brother of an index entry which can be created to describe changes + + Small Brother of an index entry which can be created to describe changes done to the index in which case plenty of additional information is not requried. - As the first 4 data members match exactly to the IndexEntry type, methods - expecting a BaseIndexEntry can also handle full IndexEntries even if they + As the first 4 data members match exactly to the IndexEntry type, methods + expecting a BaseIndexEntry can also handle full IndexEntries even if they use numeric indices for performance reasons. """ @@ -396,7 +397,7 @@ class IndexFile(LazyMixin, diff.Diffable): If 2 Trees are given, they will be merged into a new index using a two way merge algorithm. Tree 1 is the 'current' tree, tree 2 is the 'other' one. It behaves like a fast-forward. - If 3 Trees are given, a 3-way merge will be performed with the first tree + If 3 Trees are given, a 3-way merge will be performed with the first tree being the common ancestor of tree 2 and tree 3. Tree 2 is the 'current' tree, tree 3 is the 'other' one diff --git a/lib/git/refs.py b/lib/git/refs.py index 352c14f4..1900c6ce 100644 --- a/lib/git/refs.py +++ b/lib/git/refs.py @@ -3,9 +3,8 @@ # # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php -""" -Module containing all ref based objects -""" +""" Module containing all ref based objects """ + import os from objects import Object, Commit from objects.utils import get_object_type_by_name diff --git a/lib/git/remote.py b/lib/git/remote.py index b4413cce..9141fc3b 100644 --- a/lib/git/remote.py +++ b/lib/git/remote.py @@ -3,9 +3,7 @@ # # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php -""" -Module implementing a remote object allowing easy access to git remotes -""" +"""Module implementing a remote object allowing easy access to git remotes""" from errors import GitCommandError from git.utils import LazyMixin, Iterable, IterableList @@ -137,6 +135,7 @@ class PushProgress(object): ``message`` In case of the 'WRITING' operation, it contains the amount of bytes transferred. It may possibly be used for other purposes as well. + You may read the contents of the current line in self._cur_line """ pass @@ -145,15 +144,17 @@ class PushProgress(object): class PushInfo(object): """ Carries information about the result of a push operation of a single head:: - info = remote.push()[0] - info.flags # bitflags providing more information about the result - info.local_ref # Reference pointing to the local reference that was pushed - # It is None if the ref was deleted. - info.remote_ref_string # path to the remote reference located on the remote side - info.remote_ref # Remote Reference on the local side corresponding to + + info = remote.push()[0] + info.flags # bitflags providing more information about the result + info.local_ref # Reference pointing to the local reference that was pushed + # It is None if the ref was deleted. + info.remote_ref_string # path to the remote reference located on the remote side + info.remote_ref # Remote Reference on the local side corresponding to # the remote_ref_string. It can be a TagReference as well. - info.old_commit # commit at which the remote_ref was standing before we pushed + info.old_commit # commit at which the remote_ref was standing before we pushed # it to local_ref.commit. Will be None if an error was indicated + """ __slots__ = ('local_ref', 'remote_ref_string', 'flags', 'old_commit', '_remote') -- cgit v1.2.3 From 20ef1924b832a3788849793c0ee6b46dd00d4520 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 4 Nov 2009 11:27:58 +0100 Subject: initial work on tutorial.rst --- TODO | 6 +++- doc/tutorial.rst | 107 ++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 71 insertions(+), 42 deletions(-) diff --git a/TODO b/TODO index 729bb07b..42e353f2 100644 --- a/TODO +++ b/TODO @@ -43,7 +43,11 @@ Diff Docs ---- -Overhaul docs - check examples, check looks, improve existing docs +* Overhaul docs - check examples, check looks, improve existing docs +* Config: auto-generated module does not appear at all ( except for two lines ) + - its probably related to some fishy error lines: + :0: (ERROR/3) Unexpected indentation. + :0: (ERROR/3) Unexpected indentation. Index ----- diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 838fd68e..a5fe53ec 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -4,9 +4,8 @@ GitPython Tutorial ================== -GitPython provides object model access to your git repository. Once you have -created a repository object, you can traverse it to find parent commit(s), -trees, blobs, etc. +GitPython provides object model access to your git repository. This tutorial is +composed of multiple sections, each of which explain a real-life usecase. Initialize a Repo object ************************ @@ -22,83 +21,109 @@ initialize GitPython with a bare repository. >>> repo = Repo.create("/var/git/git-python.git") -Getting a list of commits -************************* +Examining References +******************** + +References are the tips of your commit graph from which you can easily examine +the history of your project. + + >>> heads = repo.heads + >>> master = heads.master # lists can be accessed by name for convenience + >>> master.commit # the commit pointed to by head called master + >>> master.rename("new_name") # rename individual heads or + >>> repo.delete_head(master) # delete them or + >>> repo.create_head('master') # create them + +Tags are (usually immutable) references to a commit and/or a tag object. + + >>> tags = repo.tags + >>> tagref = tags[0] + >>> tagref.tag # tags may have tag objects carrying additional information + >>> tagref.commit # but they always point to commits + >>> repo.delete_tag(tagref) # delete or + >>> repo.create_tag("my_tag") # create tags using the repo + +Understanding Objects +********************* +An Object is anything storable in gits object database. Objects contain information +about their type, their uncompressed size as well as their data. Each object is +uniquely identified by a SHA1 hash, being 40 hexadecimal characters in size. + +Git only knows 4 distinct object types being Blobs, Trees, Commits and Tags. + +In Git-Pyhton, all objects can be accessed through their common base, compared +and hashed, as shown in the following example. + + >>> + +Index Objects are objects that can be put into gits index. These objects are trees +and blobs which additionally know about their path in the filesystem as well as their +mode. -From the ``Repo`` object, you can get a list of ``Commit`` -objects. +The Commit object +***************** - >>> repo.commits() - [, - , - , - ] +Commit objects contain information about a specific commit. Obtain commits using +references as done in 'Examining References' or as follows -Called without arguments, ``Repo.commits`` returns a list of up to ten commits -reachable by the master branch (starting at the latest commit). You can ask -for commits beginning at a different branch, commit, tag, etc. +Obtain commits at the specified revision: - >>> repo.commits('mybranch') - >>> repo.commits('40d3057d09a7a4d61059bca9dca5ae698de58cbe') - >>> repo.commits('v0.1') + >>> repo.commit('master') + >>> repo.commit('v0.1') + >>> repo.commit('HEAD~10') -You can specify the maximum number of commits to return. +Iterate 100 commits - >>> repo.commits('master', max_count=100) + >>> repo.iter_commits('master', max_count=100) If you need paging, you can specify a number of commits to skip. - >>> repo.commits('master', max_count=10, skip=20) + >>> repo.iter_commits('master', max_count=10, skip=20) The above will return commits 21-30 from the commit list. -The Commit object -***************** - -Commit objects contain information about a specific commit. - - >>> head = repo.commits()[0] + >>> headcommit = repo.headcommit.commit - >>> head.id + >>> headcommit.sha '207c0c4418115df0d30820ab1a9acd2ea4bf4431' - >>> head.parents + >>> headcommit.parents [] - >>> head.tree + >>> headcommit.tree - >>> head.author + >>> headcommit.author "> - >>> head.authored_date - (2008, 5, 7, 5, 0, 56, 2, 128, 0) + >>> headcommit.authored_date # seconds since epoch + 1256291446 - >>> head.committer + >>> headcommit.committer "> - >>> head.committed_date - (2008, 5, 7, 5, 0, 56, 2, 128, 0) + >>> headcommit.committed_date + 1256291446 - >>> head.message + >>> headcommit.message 'cleaned up a lot of test information. Fixed escaping so it works with subprocess.' -Note: date time is represented in a `struct_time`_ format. Conversion to +Note: date time is represented in a `seconds since epock`_ format. Conversion to human readable form can be accomplished with the various time module methods. >>> import time - >>> time.asctime(head.committed_date) + >>> time.asctime(time.gmtime(headcommit.committed_date)) 'Wed May 7 05:56:02 2008' - >>> time.strftime("%a, %d %b %Y %H:%M", head.committed_date) + >>> time.strftime("%a, %d %b %Y %H:%M", time.gmtime(headcommit.committed_date)) 'Wed, 7 May 2008 05:56' .. _struct_time: http://docs.python.org/library/time.html You can traverse a commit's ancestry by chaining calls to ``parents``. - >>> repo.commits()[0].parents[0].parents[0].parents[0] + >>> headcommit.parents[0].parents[0].parents[0] The above corresponds to ``master^^^`` or ``master~3`` in git parlance. -- cgit v1.2.3 From 50af864298826feaf94772982bbc7b222b4b4242 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 4 Nov 2009 12:34:37 +0100 Subject: Worked on the tree object handling and realized an issue with attribute naming on index objects and the way the system handles these --- doc/tutorial.rst | 114 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 80 insertions(+), 34 deletions(-) diff --git a/doc/tutorial.rst b/doc/tutorial.rst index a5fe53ec..23e5de8e 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -31,8 +31,6 @@ the history of your project. >>> master = heads.master # lists can be accessed by name for convenience >>> master.commit # the commit pointed to by head called master >>> master.rename("new_name") # rename individual heads or - >>> repo.delete_head(master) # delete them or - >>> repo.create_head('master') # create them Tags are (usually immutable) references to a commit and/or a tag object. @@ -42,6 +40,28 @@ Tags are (usually immutable) references to a commit and/or a tag object. >>> tagref.commit # but they always point to commits >>> repo.delete_tag(tagref) # delete or >>> repo.create_tag("my_tag") # create tags using the repo + +A symbolic reference is a special case of a reference as it points to another +reference instead of a commit + +Modifying References +******************** +You can easily create and delete reference types or modify where they point to. + + >>> repo.delete_head('master') + >>> master = repo.create_head('master') + >>> master.commit = 'HEAD~10' # set another commit without changing index or working tree + +Create or delete tags the same way except you may not change them afterwards + + >>> new_tag = repo.create_tag('my_tag', 'my message') + >>> repo.delete_tag(new_tag) + +Change the symbolic reference to switch branches cheaply ( without adjusting the index +or the working copy ) + + >>> new_branch = repo.create_head('new_branch') + >>> repo.head.reference = new_branch Understanding Objects ********************* @@ -54,12 +74,43 @@ Git only knows 4 distinct object types being Blobs, Trees, Commits and Tags. In Git-Pyhton, all objects can be accessed through their common base, compared and hashed, as shown in the following example. - >>> + >>> hc = repo.head.commit + >>> hct = hc.tree + >>> hc != hct + >>> hc != repo.tags[0] + >>> hc == repo.head.reference.commit + +Basic fields are + + >>> hct.type + 'tree' + >>> hct.size + 166 + >>> hct.sha + 'a95eeb2a7082212c197cabbf2539185ec74ed0e8' + >>> hct.data # returns string with pure uncompressed data + '...' + >>> len(hct.data) == hct.size Index Objects are objects that can be put into gits index. These objects are trees and blobs which additionally know about their path in the filesystem as well as their mode. + >>> hct.path # root tree has no path + '' + >>> hct.trees[0].path # the first subdirectory has one though + 'dir' + >>> htc.mode # trees have mode 0 + 0 + >>> '%o' % htc.blobs[0].mode # blobs have a specific mode though comparable to a standard linux fs + 100644 + +Access blob data (or any object data) directly or using streams. + >>> htc.data # binary tree data + >>> htc.blobs[0].data_stream # stream object to read data from + >>> htc.blobs[0].stream_data(my_stream) # write data to given stream + + The Commit object ***************** @@ -133,43 +184,29 @@ The Tree object A tree records pointers to the contents of a directory. Let's say you want the root tree of the latest commit on the master branch. - >>> tree = repo.commits()[0].tree + >>> tree = repo.heads.master.commit.tree - >>> tree.id + >>> tree.sha 'a006b5b1a8115185a228b7514cdcd46fed90dc92' Once you have a tree, you can get the contents. - >>> contents = tree.values() - [, - , - , - ] - -The tree is implements a dictionary protocol so it can be used and acts just -like a dictionary with some additional properties. - - >>> tree.items() - [('lib', ), - ('LICENSE', ), - ('doc', ), - ('MANIFEST.in', ), - ('.gitignore', ), - ('test', ), - ('VERSION', ), - ('AUTHORS', ), - ('README', ), - ('ez_setup.py', ), - ('setup.py', ), - ('CHANGES', )] - -This tree contains three ``Blob`` objects and one ``Tree`` object. The trees -are subdirectories and the blobs are files. Trees below the root have -additional attributes. - - >>> contents = tree["lib"] - + >>> tree.trees # trees are subdirectories + [] + + >>> tree.blobs # blobs are files + [, + , + , + ] + +Its useful to know that a tree behaves like a list with the ability to +query entries by name. + + >>> tree[0] == tree['dir'] + + >>> for entry in tree: do_something(entry) >>> contents.name 'test' @@ -223,6 +260,15 @@ You can also get a blob directly from the repo if you know its name. >>> repo.blob("b19574431a073333ea09346eafd64e7b1908ef49") + +Handling Remotes +**************** + +Obtaining Diff Information +************************** + +Switching Branches +****************** What Else? ********** -- cgit v1.2.3 From 81279eeac5c525354cbe19b24a6f42219407c1f9 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 4 Nov 2009 14:43:54 +0100 Subject: added paragraph about using the git-python command --- doc/tutorial.rst | 82 +++++++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 23e5de8e..424e323a 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -208,11 +208,13 @@ query entries by name. >>> for entry in tree: do_something(entry) - >>> contents.name - 'test' - - >>> contents.mode - '040000' + >>> blob = tree[0][0] + >>> blob.name + 'file' + >>> blob.path + 'dir/file' + >>> blob.abspath + '/Users/mtrier/Development/git-python/dir/file' There is a convenience method that allows you to get a named sub-object from a tree with a syntax similar to how paths are written in an unix @@ -228,39 +230,17 @@ You can also get a tree directly from the repository if you know its name. >>> repo.tree("c1c7214dde86f76bc3e18806ac1f47c38b2b7a30") + >>> repo.tree('0.1.6') + + +As trees only allow direct access to their direct entries, use the traverse +method to obtain an iterator to access entries recursively. -The Blob object -*************** - -A blob represents a file. Trees often contain blobs. - - >>> blob = tree['urls.py'] - - -A blob has certain attributes. - - >>> blob.name - 'urls.py' - - >>> blob.mode - '100644' - - >>> blob.mime_type - 'text/x-python' - - >>> blob.size - 415 - -You can get the data of a blob as a string. - - >>> blob.data - "from django.conf.urls.defaults import *\nfrom django.conf..." - -You can also get a blob directly from the repo if you know its name. + >>> tree.traverse() + + >>> for entry in traverse(): do_something(entry) - >>> repo.blob("b19574431a073333ea09346eafd64e7b1908ef49") - - + Handling Remotes **************** @@ -270,13 +250,31 @@ Obtaining Diff Information Switching Branches ****************** +Using git directly +****************** +In case you are missing functionality as it has not been wrapped, you may conveniently +use the git command directly. It is owned by each repository instance. + + >>> git = repo.git + >>> git.checkout('head', b="my_new_branch") # default command + >>> git.for_each_ref() # '-' becomes '_' when calling it + +The return value will by default be a string of the standard output channel produced +by the command. + +Keyword arguments translate to short and long keyword arguments on the commandline. +The special notion `git.command(flag=True)`_ will create a flag without value like +``command --flag``. + +If ``None`` is found in the arguments, it will be dropped silently. Lists and tuples +passed as arguments will be unpacked to individual arguments. Objects are converted +to strings using the str(...) function. + What Else? ********** -There is more stuff in there, like the ability to tar or gzip repos, stats, -log, blame, and probably a few other things. Additionally calls to the git -instance are handled through a ``__getattr__`` construct, which makes -available any git commands directly, with a nice conversion of Python dicts -to command line parameters. +There is more stuff in there, like the ability to archive repositories, get stats +and logs, blame, and probably a few other things. + +Check the unit tests for an in-depth introduction on how each function is supposed to be used. -Check the unit tests, they're pretty exhaustive. -- cgit v1.2.3 From a885d23bab51b0c00be2780055ff63b3f3c1a4c6 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 4 Nov 2009 15:31:56 +0100 Subject: Added Index Object paragraph and wrote the Remote Handling paragraph. Updated repo area --- doc/tutorial.rst | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 424e323a..b5cbcc5c 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -20,7 +20,31 @@ is my working repository and contains the ``.git`` directory. You can also initialize GitPython with a bare repository. >>> repo = Repo.create("/var/git/git-python.git") + +A repo object provides high-level access to your data, it allows you to create +and delete heads, tags and remotes and access the configuration of the +repository. + + >>> repo.config_reader() # get a config reader for read-only access + >>> repo.config_writer() # get a config writer to change configuration + +Query the active branch, query untracked files or whether the repository data +has been modified. + + >>> repo.is_dirty() + False + >>> repo.untracked_files() + ['my_untracked_file'] + +Clone from existing repositories or initialize new empty ones. + >>> cloned_repo = repo.clone("to/this/path") + >>> new_repo = repo.init("path/for/new/repo") + +Archive the repository contents to a tar file. + + >>> repo.archive(open("repo.tar",'w')) + Examining References ******************** @@ -241,9 +265,55 @@ method to obtain an iterator to access entries recursively. >>> for entry in traverse(): do_something(entry) +The Index Object +**************** +The git index is the stage containing changes to be written to the next commit +or where merges finally have to take place. You may freely access and manipulate +this information using the Index Object. + + >>> index = repo.index + +Access objects and add/remove entries. Commit the changes. + + >>> for stage,blob in index.iter_blobs(): do_something(...) + Access blob objects + >>> for (path,stage),entry in index.entries.iteritems: pass + Access the entries directly + >>> index.add(['my_new_file']) # add a new file to the index + >>> index.remove(['dir/existing_file']) + >>> new_commit = index.commit("my commit message") + +Create new indices from other trees or as result of a merge. Write that result to +a new index. + + >>> tmp_index = Index.from_tree(repo, 'HEAD~1') # load a tree into a temporary index + >>> merge_index = Index.from_tree(repo, 'HEAD', 'some_branch') # merge two trees + >>> merge_index.write("merged_index") + Handling Remotes **************** +Remotes are used as alias for a foreign repository to ease pushing to and fetching +from them. + + >>> test_remote = repo.create_remote('test', 'git@server:repo.git') + >>> repo.delete_remote(test_remote) # create and delete remotes + >>> origin = repo.remotes.origin # get default remote by name + >>> origin.refs # local remote references + >>> o = origin.rename('new_origin') # rename remotes + >>> o.fetch() # fetch, pull and push from and to the remote + >>> o.pull() + >>> o.push() + +You can easily access configuration information for a remote by accessing options +as if they where attributes. + + >>> o.url + 'git@server:dummy_repo.git' + +Change configuration for a specific remote only + >>> o.config_writer.set("url", "other_url") + Obtaining Diff Information ************************** -- cgit v1.2.3 From 9117cdbb48ffc458d809715c6ab6bc6b416ef621 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 4 Nov 2009 16:19:07 +0100 Subject: added paragraph about the diffing engine and how to switch branches, which once more shows the need for a real checkout for all the people who do not want to implement all the safety facilities themselves --- doc/tutorial.rst | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/doc/tutorial.rst b/doc/tutorial.rst index b5cbcc5c..f4c9e71d 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -317,8 +317,41 @@ Change configuration for a specific remote only Obtaining Diff Information ************************** +Diffs can generally be obtained by Subclasses of ``Diffable`` as they provide +the ``diff`` method. This operation yields a DiffIndex allowing you to easily access +diff information about paths. + +Diffs can be made between Index and Trees, Index and the working tree, trees and +trees as well as trees and the working copy. If commits are involved, their tree +will be used implicitly. + + >>> hcommit = repo.head.commit + >>> idiff = hcommit.diff() # diff tree against index + >>> tdiff = hcommit.diff('HEAD~1') # diff tree against previous tree + >>> wdiff = hcommit.diff(None) # diff tree against working tree + + >>> index = repo.index + >>> index.diff() # diff index against itself yielding empty diff + >>> index.diff(None) # diff index against working copy + >>> index.diff('HEAD') # diff index against current HEAD tree + +The item returned is a DiffIndex which is essentially a list of Diff objects. It +provides additional filtering to find what you might be looking for + + >>> for diff_added in wdiff.iter_change_type('A'): do_something(diff_added) + Switching Branches ****************** +To switch between branches, you effectively need to point your HEAD to the new branch +head and reset your index and working copy to match. A simple manual way to do it +is the following one. + + >>> repo.head.reference = repo.heads.other_branch + >>> repo.head.reset(index=True, working_tree=True + +The previous approach would brutally overwrite the user's changes in the working copy +and index though and is less sophisticated than a git-checkout for instance which +generally prevents you from destroying your work. Using git directly ****************** @@ -340,11 +373,11 @@ If ``None`` is found in the arguments, it will be dropped silently. Lists and tu passed as arguments will be unpacked to individual arguments. Objects are converted to strings using the str(...) function. -What Else? -********** +And even more ... +***************** -There is more stuff in there, like the ability to archive repositories, get stats -and logs, blame, and probably a few other things. +There is more functionality in there, like the ability to archive repositories, get stats +and logs, blame, and probably a few other things that were not mentioned here. Check the unit tests for an in-depth introduction on how each function is supposed to be used. -- cgit v1.2.3 From fc2201e660014c5d91fec8e3c3a3fa5a66dcf33b Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 4 Nov 2009 17:10:07 +0100 Subject: Converted tabs to spaces. Set required mock version to 0.5 --- doc/intro.rst | 2 +- doc/tutorial.rst | 236 +++++++++++++++++++++++++++---------------------------- 2 files changed, 119 insertions(+), 119 deletions(-) diff --git a/doc/intro.rst b/doc/intro.rst index c5843a1f..f08a7ec5 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -16,7 +16,7 @@ Requirements * Git_ tested with 1.5.3.7 * `Python Nose`_ - used for running the tests -* `Mock by Michael Foord`_ used for tests. Requires 0.4 +* `Mock by Michael Foord`_ used for tests. Requires 0.5 .. _Git: http://git-scm.com/ .. _Python Nose: http://code.google.com/p/python-nose/ diff --git a/doc/tutorial.rst b/doc/tutorial.rst index f4c9e71d..f48aceb0 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -24,27 +24,27 @@ initialize GitPython with a bare repository. A repo object provides high-level access to your data, it allows you to create and delete heads, tags and remotes and access the configuration of the repository. - - >>> repo.config_reader() # get a config reader for read-only access - >>> repo.config_writer() # get a config writer to change configuration + + >>> repo.config_reader() # get a config reader for read-only access + >>> repo.config_writer() # get a config writer to change configuration Query the active branch, query untracked files or whether the repository data has been modified. - - >>> repo.is_dirty() - False - >>> repo.untracked_files() - ['my_untracked_file'] - + + >>> repo.is_dirty() + False + >>> repo.untracked_files() + ['my_untracked_file'] + Clone from existing repositories or initialize new empty ones. - >>> cloned_repo = repo.clone("to/this/path") - >>> new_repo = repo.init("path/for/new/repo") - + >>> cloned_repo = repo.clone("to/this/path") + >>> new_repo = repo.init("path/for/new/repo") + Archive the repository contents to a tar file. - >>> repo.archive(open("repo.tar",'w')) - + >>> repo.archive(open("repo.tar",'w')) + Examining References ******************** @@ -52,19 +52,19 @@ References are the tips of your commit graph from which you can easily examine the history of your project. >>> heads = repo.heads - >>> master = heads.master # lists can be accessed by name for convenience - >>> master.commit # the commit pointed to by head called master - >>> master.rename("new_name") # rename individual heads or + >>> master = heads.master # lists can be accessed by name for convenience + >>> master.commit # the commit pointed to by head called master + >>> master.rename("new_name") # rename individual heads or Tags are (usually immutable) references to a commit and/or a tag object. - >>> tags = repo.tags - >>> tagref = tags[0] - >>> tagref.tag # tags may have tag objects carrying additional information - >>> tagref.commit # but they always point to commits - >>> repo.delete_tag(tagref) # delete or - >>> repo.create_tag("my_tag") # create tags using the repo - + >>> tags = repo.tags + >>> tagref = tags[0] + >>> tagref.tag # tags may have tag objects carrying additional information + >>> tagref.commit # but they always point to commits + >>> repo.delete_tag(tagref) # delete or + >>> repo.create_tag("my_tag") # create tags using the repo + A symbolic reference is a special case of a reference as it points to another reference instead of a commit @@ -72,20 +72,20 @@ Modifying References ******************** You can easily create and delete reference types or modify where they point to. - >>> repo.delete_head('master') - >>> master = repo.create_head('master') - >>> master.commit = 'HEAD~10' # set another commit without changing index or working tree + >>> repo.delete_head('master') + >>> master = repo.create_head('master') + >>> master.commit = 'HEAD~10' # set another commit without changing index or working tree Create or delete tags the same way except you may not change them afterwards - >>> new_tag = repo.create_tag('my_tag', 'my message') - >>> repo.delete_tag(new_tag) - + >>> new_tag = repo.create_tag('my_tag', 'my message') + >>> repo.delete_tag(new_tag) + Change the symbolic reference to switch branches cheaply ( without adjusting the index or the working copy ) - >>> new_branch = repo.create_head('new_branch') - >>> repo.head.reference = new_branch + >>> new_branch = repo.create_head('new_branch') + >>> repo.head.reference = new_branch Understanding Objects ********************* @@ -98,43 +98,43 @@ Git only knows 4 distinct object types being Blobs, Trees, Commits and Tags. In Git-Pyhton, all objects can be accessed through their common base, compared and hashed, as shown in the following example. - >>> hc = repo.head.commit - >>> hct = hc.tree - >>> hc != hct - >>> hc != repo.tags[0] - >>> hc == repo.head.reference.commit - + >>> hc = repo.head.commit + >>> hct = hc.tree + >>> hc != hct + >>> hc != repo.tags[0] + >>> hc == repo.head.reference.commit + Basic fields are - >>> hct.type - 'tree' - >>> hct.size - 166 - >>> hct.sha - 'a95eeb2a7082212c197cabbf2539185ec74ed0e8' - >>> hct.data # returns string with pure uncompressed data - '...' - >>> len(hct.data) == hct.size - + >>> hct.type + 'tree' + >>> hct.size + 166 + >>> hct.sha + 'a95eeb2a7082212c197cabbf2539185ec74ed0e8' + >>> hct.data # returns string with pure uncompressed data + '...' + >>> len(hct.data) == hct.size + Index Objects are objects that can be put into gits index. These objects are trees and blobs which additionally know about their path in the filesystem as well as their mode. - >>> hct.path # root tree has no path - '' - >>> hct.trees[0].path # the first subdirectory has one though - 'dir' - >>> htc.mode # trees have mode 0 - 0 - >>> '%o' % htc.blobs[0].mode # blobs have a specific mode though comparable to a standard linux fs - 100644 - + >>> hct.path # root tree has no path + '' + >>> hct.trees[0].path # the first subdirectory has one though + 'dir' + >>> htc.mode # trees have mode 0 + 0 + >>> '%o' % htc.blobs[0].mode # blobs have a specific mode though comparable to a standard linux fs + 100644 + Access blob data (or any object data) directly or using streams. - >>> htc.data # binary tree data - >>> htc.blobs[0].data_stream # stream object to read data from - >>> htc.blobs[0].stream_data(my_stream) # write data to given stream - - + >>> htc.data # binary tree data + >>> htc.blobs[0].data_stream # stream object to read data from + >>> htc.blobs[0].stream_data(my_stream) # write data to given stream + + The Commit object ***************** @@ -171,7 +171,7 @@ The above will return commits 21-30 from the commit list. >>> headcommit.author "> - >>> headcommit.authored_date # seconds since epoch + >>> headcommit.authored_date # seconds since epoch 1256291446 >>> headcommit.committer @@ -184,7 +184,7 @@ The above will return commits 21-30 from the commit list. 'cleaned up a lot of test information. Fixed escaping so it works with subprocess.' -Note: date time is represented in a `seconds since epock`_ format. Conversion to +Note: date time is represented in a ``seconds since epock`` format. Conversion to human readable form can be accomplished with the various time module methods. >>> import time @@ -216,14 +216,14 @@ the root tree of the latest commit on the master branch. Once you have a tree, you can get the contents. - >>> tree.trees # trees are subdirectories + >>> tree.trees # trees are subdirectories [] - >>> tree.blobs # blobs are files + >>> tree.blobs # blobs are files [, - , - , - ] + , + , + ] Its useful to know that a tree behaves like a list with the ability to query entries by name. @@ -260,60 +260,60 @@ You can also get a tree directly from the repository if you know its name. As trees only allow direct access to their direct entries, use the traverse method to obtain an iterator to access entries recursively. - >>> tree.traverse() - - >>> for entry in traverse(): do_something(entry) + >>> tree.traverse() + + >>> for entry in traverse(): do_something(entry) - + The Index Object **************** The git index is the stage containing changes to be written to the next commit or where merges finally have to take place. You may freely access and manipulate this information using the Index Object. - >>> index = repo.index - + >>> index = repo.index + Access objects and add/remove entries. Commit the changes. - >>> for stage,blob in index.iter_blobs(): do_something(...) - Access blob objects - >>> for (path,stage),entry in index.entries.iteritems: pass - Access the entries directly - >>> index.add(['my_new_file']) # add a new file to the index - >>> index.remove(['dir/existing_file']) - >>> new_commit = index.commit("my commit message") - + >>> for stage,blob in index.iter_blobs(): do_something(...) + Access blob objects + >>> for (path,stage),entry in index.entries.iteritems: pass + Access the entries directly + >>> index.add(['my_new_file']) # add a new file to the index + >>> index.remove(['dir/existing_file']) + >>> new_commit = index.commit("my commit message") + Create new indices from other trees or as result of a merge. Write that result to a new index. - >>> tmp_index = Index.from_tree(repo, 'HEAD~1') # load a tree into a temporary index - >>> merge_index = Index.from_tree(repo, 'HEAD', 'some_branch') # merge two trees - >>> merge_index.write("merged_index") - + >>> tmp_index = Index.from_tree(repo, 'HEAD~1') # load a tree into a temporary index + >>> merge_index = Index.from_tree(repo, 'HEAD', 'some_branch') # merge two trees + >>> merge_index.write("merged_index") + Handling Remotes **************** Remotes are used as alias for a foreign repository to ease pushing to and fetching from them. - >>> test_remote = repo.create_remote('test', 'git@server:repo.git') - >>> repo.delete_remote(test_remote) # create and delete remotes - >>> origin = repo.remotes.origin # get default remote by name - >>> origin.refs # local remote references - >>> o = origin.rename('new_origin') # rename remotes - >>> o.fetch() # fetch, pull and push from and to the remote - >>> o.pull() - >>> o.push() + >>> test_remote = repo.create_remote('test', 'git@server:repo.git') + >>> repo.delete_remote(test_remote) # create and delete remotes + >>> origin = repo.remotes.origin # get default remote by name + >>> origin.refs # local remote references + >>> o = origin.rename('new_origin') # rename remotes + >>> o.fetch() # fetch, pull and push from and to the remote + >>> o.pull() + >>> o.push() You can easily access configuration information for a remote by accessing options as if they where attributes. - >>> o.url - 'git@server:dummy_repo.git' - + >>> o.url + 'git@server:dummy_repo.git' + Change configuration for a specific remote only - >>> o.config_writer.set("url", "other_url") - + >>> o.config_writer.set("url", "other_url") + Obtaining Diff Information ************************** @@ -325,20 +325,20 @@ Diffs can be made between Index and Trees, Index and the working tree, trees and trees as well as trees and the working copy. If commits are involved, their tree will be used implicitly. - >>> hcommit = repo.head.commit - >>> idiff = hcommit.diff() # diff tree against index - >>> tdiff = hcommit.diff('HEAD~1') # diff tree against previous tree - >>> wdiff = hcommit.diff(None) # diff tree against working tree - - >>> index = repo.index - >>> index.diff() # diff index against itself yielding empty diff - >>> index.diff(None) # diff index against working copy - >>> index.diff('HEAD') # diff index against current HEAD tree + >>> hcommit = repo.head.commit + >>> idiff = hcommit.diff() # diff tree against index + >>> tdiff = hcommit.diff('HEAD~1') # diff tree against previous tree + >>> wdiff = hcommit.diff(None) # diff tree against working tree + + >>> index = repo.index + >>> index.diff() # diff index against itself yielding empty diff + >>> index.diff(None) # diff index against working copy + >>> index.diff('HEAD') # diff index against current HEAD tree The item returned is a DiffIndex which is essentially a list of Diff objects. It provides additional filtering to find what you might be looking for - >>> for diff_added in wdiff.iter_change_type('A'): do_something(diff_added) + >>> for diff_added in wdiff.iter_change_type('A'): do_something(diff_added) Switching Branches ****************** @@ -346,9 +346,9 @@ To switch between branches, you effectively need to point your HEAD to the new b head and reset your index and working copy to match. A simple manual way to do it is the following one. - >>> repo.head.reference = repo.heads.other_branch - >>> repo.head.reset(index=True, working_tree=True - + >>> repo.head.reference = repo.heads.other_branch + >>> repo.head.reset(index=True, working_tree=True + The previous approach would brutally overwrite the user's changes in the working copy and index though and is less sophisticated than a git-checkout for instance which generally prevents you from destroying your work. @@ -358,15 +358,15 @@ Using git directly In case you are missing functionality as it has not been wrapped, you may conveniently use the git command directly. It is owned by each repository instance. - >>> git = repo.git - >>> git.checkout('head', b="my_new_branch") # default command - >>> git.for_each_ref() # '-' becomes '_' when calling it - + >>> git = repo.git + >>> git.checkout('head', b="my_new_branch") # default command + >>> git.for_each_ref() # '-' becomes '_' when calling it + The return value will by default be a string of the standard output channel produced by the command. Keyword arguments translate to short and long keyword arguments on the commandline. -The special notion `git.command(flag=True)`_ will create a flag without value like +The special notion ``git.command(flag=True)`` will create a flag without value like ``command --flag``. If ``None`` is found in the arguments, it will be dropped silently. Lists and tuples -- cgit v1.2.3