- Notifications
You must be signed in to change notification settings - Fork1.3k
The Git interface you've been missing all your life has finally arrived.
License
git-up/GitUp
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Work quickly, safely, and without headaches. The Git interface you've been missing all your life has finally arrived.
Git recently celebrated its 10 years anniversary, but most engineers are still confused by its intricacy (3 of thetop 5 questions of all time on Stack Overflow are Git related). Since Git turns even simple actions into mystifying commands (“git add” to stage versus “git reset HEAD” to unstage anyone?), it’s no surprise users waste time, get frustrated, distract the rest of their team for help, or worse, screw up their repo!
GitUp is a bet to invent a new Git interaction model that lets engineers of all levels work quickly, safely, and without headaches. It's unlike any other Git client out there from the way it’s built (it interacts directly with the Git database on disk), to the way it works (you manipulate the repository graph instead of manipulating commits).
With GitUp, you get a truly efficient Git client for Mac:
- Alive and interactive repo graph (edit, reorder, fixup, merge commits…),
- Unlimited undo / redo of almost all operations (even rebases and merges),
- Time Machine likesnapshots for 1-click rollbacks to previous repo states,
- Features that don’t even exist natively in Git like avisual commit splitter or aunified reflog browser,
- Instant search across the entire repo including diff contents,
- Aridiculously fast UI, often faster than the command line.
GitUp was created by@swisspol in late 2014 as a bet to reinvent the way developers interact with Git. After several months of work, it was made available in pre-release early 2015 and reached thetop of Hacker News along with beingfeatured by Product Hunt andDaring Fireball. 30,000 lines of code later, GitUp reached 1.0 mid-August 2015 and was released open source as a gift to the developer community.
- Official website:https://gitup.co
- Latest release on GitHub:https://github.com/git-up/GitUp/releases
- Homebrew (Not maintained by GitUp developers):
brew install homebrew/cask/gitup
(Note: There is already a formula called gitup, so the full name must be specified!)
Read thedocs and useGitHub Issues for support & feedback.
Releases notes are available athttps://github.com/git-up/GitUp/releases. Builds tagged with av
(e.g.v1.2.3
) are released on the "Stable" channel, while builds tagged with ab
(e.g.b1234
) are only released on the "Continuous" channel. You can change the update channel used by GitUp in the app preferences.
To build GitUp yourself, simply run the commandgit clone --recursive https://github.com/git-up/GitUp.git
in Terminal, then open theGitUp/GitUp.xcodeproj
Xcode project and hit Run.
IMPORTANT: If you do not have an Apple ID with a developer account for code signing Mac apps, the build will fail with a code signing error. Simply delete the "Code Signing Identity" build setting of the "Application" target to work around the issue:
Alternatively, if you do have a developer account, you can create the file "Xcode-Configurations/DEVELOPMENT_TEAM.xcconfig" with the following build setting as its content:
DEVELOPMENT_TEAM = [Your TeamID]
For a more detailed description of this, you can have a look at the comments at the end of the file "Xcode-Configurations/Base.xcconfig".
GitUp is built as a thin layer on top of a reusable generic Git toolkit called "GitUpKit". This means that you can use that same GitUpKit framework to build your very own Git UI!
GitUpKit has a very different goal thanObjectiveGit. Instead of offering extensive raw bindings tolibgit2, GitUpKit only uses a minimal subset of libgit2 and reimplements everything else on top of it (it has its own "rebase engine" for instance).This allows it to expose a very tight and consistent API, that completely follows Obj-C conventions and hides away the libgit2 complexity and sometimes inconsistencies. GitUpKit adds on top of that a number of exclusive and powerful features, from undo/redo and Time Machine like snapshots, to entire drop-in UI components.
The GitUpKit source code is organized as 2 independent layers communicating only through the use of public APIs:
Base Layer (depends on Foundation only and is compatible with OS X and iOS)
Core/
: wrapper around the required minimal functionality oflibgit2, on top of which is then implemented all the Git functionality required by GitUp (note that GitUp uses aslightly customized fork of libgit2)Extensions/
: categories on theCore
classes to add convenience features implemented only using the public APIs
UI Layer (depends on AppKit and is compatible with OS X only)
Interface/
: low-level view classes e.g.GIGraphView
to render the GitUp Map viewUtilities/
: interface utility classes e.g. the base view controller classGIViewController
Components/
: reusable single-view view controllers e.g.GIDiffContentsViewController
to render a diffViews/
: high-level reusable multi-views view controllers e.g.GIAdvancedCommitViewController
to implement the entire GitUp Advanced Commit view
IMPORTANT: If the preprocessor constantDEBUG
is defined to a non-zero value when building GitUpKit (this is the default when building in "Debug" configuration), a number of extra consistency checks are enabled at run time as well as extra logging. Be aware that this overhead can significantly affect performance.
Using the GitUpKit API should be pretty straightforward since it is organized by functionality (e.g. repository, branches, commits, interface components, etc...) and a best effort has been made to name functions clearly.
Regarding the "Core" APIs, the best way to learn them is to peruse the associated unit tests - for instance seethe branch tests for the branch API.
Here is some sample code to get you started (error handling is left as an exercise to the reader):
Opening and browsing a repository:
// Open repoGCRepository* repo = [[GCRepositoryalloc]initWithExistingLocalRepository:<PATH>error:NULL];// Make sure repo is cleanassert([repocheckClean:kGCCleanCheckOption_IgnoreUntrackedFileserror:NULL]);// List all branchesNSArray* branches = [repolistAllBranches:NULL];NSLog(@"%@", branches);// Lookup HEADGCLocalBranch* headBranch;// This would be nil if the HEAD is detachedGCCommit* headCommit;[repolookupHEADCurrentCommit:&headCommitbranch:&headBrancherror:NULL];NSLog(@"%@ =%@", headBranch, headCommit);// Load the *entire* repo history in memory for fast access, including all commits, branches and tagsGCHistory* history = [repoloadHistoryUsingSorting:kGCHistorySorting_ReverseChronologicalerror:NULL];assert(history);NSLog(@"%lu commits total", history.allCommits.count);NSLog(@"%@\n%@", history.rootCommits, history.leafCommits);
Modifying a repository:
// Take a snapshot of the repoGCSnapshot* snapshot = [repotakeSnapshot:NULL];// Create a new branch and check it outGCLocalBranch* newBranch = [repocreateLocalBranchFromCommit:headCommitwithName:@"temp"force:NOerror:NULL];NSLog(@"%@", newBranch);assert([repocheckoutLocalBranch:newBranchoptions:0error:NULL]);// Add a file to the index[[NSDatadata]writeToFile:[repo.workingDirectoryPathstringByAppendingPathComponent:@"empty.data"]atomically:YES];assert([repoaddFileToIndex:@"empty.data"error:NULL]);// Check index statusGCDiff* diff = [repodiffRepositoryIndexWithHEAD:niloptions:0maxInterHunkLines:0maxContextLines:0error:NULL];assert(diff.deltas.count ==1);NSLog(@"%@", diff);// Create a commitGCCommit* newCommit = [repocreateCommitFromHEADWithMessage:@"Added file"error:NULL];assert(newCommit);NSLog(@"%@", newCommit);// Restore repo to saved snapshot before topic branch and commit were createdBOOL success = [reporestoreSnapshot:snapshotwithOptions:kGCSnapshotOption_IncludeAllreflogMessage:@"Rolled back"didUpdateReferences:NULLerror:NULL];assert(success);// Make sure topic branch is goneassert([repofindLocalBranchWithName:@"temp"error:NULL] ==nil);// Update workdir and index to match HEADassert([reporesetToHEAD:kGCResetMode_Harderror:NULL]);
GitDown is a very basic app that prompts the user for a repo and displays an interactive and live-updating list of its stashes (all with ~20 lines of code in-[AppDelegate applicationDidFinishLaunching:]
):
Through GitUpKit, this basic app also gets for free unlimited undo/redo, unified and side-by-side diffs, text selection and copy, keyboard shortcuts, etc...
This source code also demonstrates how to use some other GitUpKit view controllers as well as building a customized one.
GitDiff demonstrates how to create a view controller that displays a live updating diff betweenHEAD
and the workdir à lagit diff HEAD
:
GitY is aGitX clone built using GitUpKit and less than 200 lines of code:
iGit is a test iOS app that simply uses GitUpKit to clone a GitHub repo and perform a commit.
SeeCONTRIBUTING.md.
Also a big thanks to the finelibgit2 contributors without whom GitUp would have never existed!
GitUp is copyright 2015-2018 Pierre-Olivier Latour and available underGPL v3 license. See theLICENSE file in the project for more information.
IMPORTANT: GitUp includes some other open-source projects and such projects remain under their own license.
About
The Git interface you've been missing all your life has finally arrived.