November 1, 2012 briandoll

Drinkup in Sofia, Bulgaria

Sofia Rocks! Join Nick and I along with all the great folks attending OpenFest for a pint at RockIT, Sofia's most awesome rock and metal bar. The party starts at 7pm. See you there!

The Facts

October 31, 2012 watsonian

GitHub Enterprise 11.10.290 Release

We're excited to announce the latest release of GitHub Enterprise. We're shipping this version with our new Command Bar, User Profile Pages, and much more. Along with a variety of general improvements and adjustments, this new release brings the following features from GitHub.com:

In addition, we're also including several new Enterprise specific features:

Audit Logs

We've had detailed audit logs that we use from GitHub.com for quite some time now. After a lot of work, this same audit logging system is now available in Enterprise. This means that Security History for users and repositories is now available:

There are also push logs for every repository that let you track commits made by users – including which IP the push originated from, the protocol the push occurred over, the user agent for the client that was used, and the SHA before and after the push. Force pushes are noted when they occur:

These logs are included in the log forwarding streams, so you can save them remotely in secure locations for compliance reasons or for better searchability.

Improved Search Backend

Over the last few months, we've been working hard to improve the search experience. We've completely replaced the old backend with ElasticSearch. User, Repository, and Code searching is much faster, with more consistent indexing behavior, and yields better results.

Maintenance Mode

There's now a method to put the installation into maintenance mode. While in this mode, users will be directed to a maintenance page when attempting to browse to the installation and git operations will be rejected with a maintenance message.

Any installation admin can enable maintenance mode at any time via the Management Console. The support email address that's mentioned can be customized as well.

Updated Management Console UI

The UI for the Management Console has had a bit of a touchup:


We hope you enjoy these features as much as we do. Don't forget that there is more information available about GitHub Enterprise at https://enterprise.github.com/. You can also see the full release notes here.

October 30, 2012 kamzilla

The Second Annual Octocat Dodgeball Invitational is almost here

We're less than two weeks away from our second annual Octocat Dodgeball Invitational. Last year we raised $57,000 for charities around the world and did some real good in the universe. Well, we also threw a lot of balls at other companies, too.

We even whipped up a special commemorative 2011 memorial video presentation to get you pumped up for this year's dodgefest:

Dodgeball is nothing without you and your team, though! Sign up today, donate, and join us in battle on November 11th at the SoMa Recreation Center. We'll be playing for four amazing local charities: 826 Valencia, Streetside Stories, SF Public Libraries, and Second Harvest Food Bank.

Winners will join Heroku on the magnificent OctoTrophy:

Dodging balls ain't your thing? Still want to join in on the fun? We'll be streaming all the action live to the big screens at Jillian's. Watch the elimination rounds and tournament finals while enjoying a :beer: or two on us.

Space is limited at Jillian's, so please register today.

Remember: code is cool and all, but it won't stop a dodgeball. Yet.

October 30, 2012 rsanheim

New close and merge notifications

We have just added notifications when a Pull Request is merged and when an Issue/Pull Request is closed or reopened.

Issue Close:

Merged Pull Request:

You get the idea — happy notifying!

October 26, 2012 technoweenie

Notifications API

Now that the dust has settled around Notifications and Stars, we've unleashed all that :sparkles: in a brand new API. You can now view and mark notifications as read.

The core notifications functionality is under the /notifications endpoint. You can look for unread notifications:

$ curl https://api.github.com/notifications

You can filter these notifications to a single Repository:

$ curl https://api.github.com/repos/technoweenie/faraday/notifications

You can read more about this on the API Changes blog, or the full Notifications API documentation.

October 26, 2012 tlberglund

Denver Public Git Workshop

We are delighted to announce our first public workshop in Denver, Colorado. Matthew and I on the training team spend most of our time traveling away from Denver to teach the subject we love, so we thought it only made sense to hold a workshop open to the public in our home city. We've also done some work to get the price low enough to drive as much community participation as possible. For $195, you can join us for a day of Git Foundations, which includes:

  • The history of Git
  • Configuration
  • Git's three-stage thinking
  • Comparing file differences
  • Looking at history
  • Moving files
  • Branching and merging
  • Rebasing
  • Collaboration using GitHub

Register here:

Denver Public Git Workshop

October 25, 2012 leereilly

GitHub Game Off

Here at GitHub, we're no strangers to hosting or sponsoring hackathons. With the growing number of games and game development resources on GitHub, we thought it was about time to throw our very own game jam!

GitHub Mega Cat

The Challenge

You have the entire month of November to create a web-based game loosely built around one or more of the following themes:

  • forking (or forks)
  • branching (or branches)
  • cloning (or clones)
  • pushing
  • pulling

What do we mean by loosely based on these concepts? We literally mean, loosely based. Some examples might be a FPS where you throw forks at water balloons, an educational game about DNA cloning, or perhaps a platformer where you push and pull objects.

Your game. Your rules. You can participate as an individual or as a team. You're encouraged to use open source libraries, frameworks, graphics, and sounds.

Prizes

We have 5 shiny new iPads with Retina displays (64GB wifi models) to give to our winners (or Apple Store Credit equivalent). Runners up will receive GitHub swag of their choice ($100 credit for the GitHub Shop). If you have a team submission, we'll give you Apple Store credit equal to the value of the iPad. You can split it with your teammates as appropriate.

All of the winners and runners up will be showcased on our blog.

Everyone's a winner!

All participants will receive a limited edition Coderwall badge as shown above. Winners and runners up will also get their own special version of it.

Judging

We have a number of awesome judges who graciously volunteered to take a look at all the entries!

Rules

  • To qualify for entry as an individual you must fork the github/game-off-2012 repository to your individual account
  • To qualify for entry as a team you must fork the github/game-off-2012 to a free organization account
  • All entries must be web-based, i.e. playable in a browser. HTML5, WebGL, Unity, Torque 3D, Node JS, Flash are all possible - just be sure the source is made available on your fork.
  • You must be over the age of 13

Instructions

  • If you don't already have a GitHub account, sign up now - it's free!
  • Fork the github/game-off-2012 repository to your individual account (or to a free organization account)
  • Be sure to follow @github on Twitter for updates
  • Make sure your code is pushed to the master branch of your forked repository before Dec 1st!
  • Make sure you have a README file that includes a brief description, what open source projects (if any) you used, and a screenshot.
  • Your repo should have a brief description and a URL where the game is playable entered into the fields shown below (this will make our judging process easier):

Winners will be announced before Christmas :santa:

Comments / Questions / Help

  • New to Git, GitHub, and/or version control? Check out our help documentation to get started!
  • Questions about Git/GitHub? Please email support@github.com and be sure to include 'GitHub Game Off' in the subject.
  • Questions specific to the GitHub Game Off? Please create an issue. That will be the official FAQ.
  • The official Twitter hashtag is #ggo12.

October 23, 2012 jspahrsummers

Rebel: a Framework for Improving AppKit

In our last blog post, we revealed Mantle, our Cocoa model framework. Today, we're announcing Rebel, a framework for improving AppKit.

Since you may recall our original TwUI announcement, the decision to start using AppKit again bears some explanation.

Farewell, TwUI

For a while now, we’ve been collaborators on Twitter’s TwUI, a popular UI framework for the Mac. TwUI made it easy to build a modern layer-based application for OS X.

However, the AppKit improvements in Lion and Mountain Lion include substantial fixes for layer-backed views. On Snow Leopard, layer-backed NSTextFields and NSTextViews were almost unusable – now, most standard views behave sanely. NSScrollView, in particular, no longer consumes an absurd amount of memory or performs asynchronous tiling (so content no longer fades in while scrolling).

These fixes make TwUI less necessary, so we're slowly migrating GitHub for Mac back to be 100% AppKit, freeing up our development time to work on GitHub for Mac instead of maintaining an entire UI framework alongside it.

As we move away from using TwUI, we will also become less active in its development. We want to leave the framework in good hands, though, so if you're interested in helping maintain TwUI, please open an issue and explain why you think you'd be a good fit.

It's Not All Peaches and Cream

Still, AppKit isn't perfect.

Some significant improvements are only available on Mountain Lion. Even then, there are still some bugs – silly things like horizontally scrolling NSTextFields ending up on half pixels, or NSScrollView being unbearably slow.

Not to mention that many of its APIs are often difficult to use:

  • NSCell is the perennial example. Support for views (instead of cells) in NSTableView helped a lot, but NSControl still uses a cell.
  • Three-slice and nine-slice images are a pain to draw.
  • NSPopover doesn't support much appearance customization.
  • Animator proxies don't immediately reflect changes, and always animate, even when outside of an explicit animation group. Together, these behaviors make it impossible to write a single code path that performs correct layout regardless of whether an animation is occurring.

Introducing Rebel

This is where Rebel comes in. Rebel aims to solve the above problems, and whatever else we may run into.

There are fixes to the NSTextField blurriness and NSScrollView performance. There are iOS-like resizable images. Let Rebel figure out whether you're animating or not.

Have you seen the username autocompletion popover?

Username autocompletion
popover

That's RBLPopover at work!

We want to make AppKit easy and enjoyable to use without rewriting it from the ground up.

Getting Involved

Rebel is currently alpha quality. We're already using it in GitHub for Mac, but we may still make breaking changes occasionally.

So, check it out, enjoy, and please file any issues that you find!

October 22, 2012 hotbootymasala

Alyson Heineman La is a GitHubber!

Alyson joins us as our second hire in the finance department and will be working on day-to-day accounting tasks that keep the wheels turning. Having worked for GitHub in the past in a consultant capacity, we are absolutely thrilled to have finally captured her as an official Hubbernaut. Alyson will also be dedicated to our efforts of changing age-old perceptions of the stereotypical accountant.

Follow her on Twitter and GitHub.

October 22, 2012 kneath

Latest commit per directory

We've always shown the last commit to the Branch or Tag you're browsing on the root page of a repository:

Now, we also show the latest commit per directory — meaning the last commit that touched anything underneath that directory

Enjoy!

October 22, 2012 jspahrsummers

Mantle: a Model Framework for Objective-C

Lately, we've been shipping more in GitHub for Mac than ever before. Now that username autocompletion and Notification Center support are out the door, we're releasing the two frameworks that helped make it happen.

This post talks about Mantle, our framework that makes it dead simple to create a flexible and easy-to-use model layer in Cocoa or Cocoa Touch. In our next blog post, we'll talk about Rebel, our framework for improving AppKit.

First, let's explore why you would even want such a framework. What's wrong with the way model objects are usually written in Objective-C?

The Typical Model Object

Let's use the GitHub API for demonstration. How would one typically represent a GitHub issue in Objective-C?

typedef enum : NSUInteger {
    GHIssueStateOpen,
    GHIssueStateClosed
} GHIssueState;

@interface GHIssue : NSObject <NSCoding, NSCopying>

@property (nonatomic, copy, readonly) NSURL *URL;
@property (nonatomic, copy, readonly) NSURL *HTMLURL;
@property (nonatomic, copy, readonly) NSNumber *number;
@property (nonatomic, assign, readonly) GHIssueState state;
@property (nonatomic, copy, readonly) NSString *reporterLogin;
@property (nonatomic, copy, readonly) NSString *assigneeLogin;
@property (nonatomic, copy, readonly) NSDate *updatedAt;

@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *body;

- (id)initWithDictionary:(NSDictionary *)dictionary;

@end
@implementation GHIssue

+ (NSDateFormatter *)dateFormatter {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'Z'";
    return dateFormatter;
}

- (id)initWithDictionary:(NSDictionary *)dictionary {
    self = [self init];
    if (self == nil) return nil;

    _URL = [NSURL URLWithString:dictionary[@"url"]];
    _HTMLURL = [NSURL URLWithString:dictionary[@"html_url"]];
    _number = dictionary[@"number"];

    if ([dictionary[@"state"] isEqualToString:@"open"]) {
        _state = GHIssueStateOpen;
    } else if ([dictionary[@"state"] isEqualToString:@"closed"]) {
        _state = GHIssueStateClosed;
    }

    _title = [dictionary[@"title"] copy];
    _body = [dictionary[@"body"] copy];
    _reporterLogin = [dictionary[@"user"][@"login"] copy];
    _assigneeLogin = [dictionary[@"assignee"][@"login"] copy];

    _updatedAt = [self.class.dateFormatter dateFromString:dictionary[@"updated_at"]];

    return self;
}

- (id)initWithCoder:(NSCoder *)coder {
    self = [self init];
    if (self == nil) return nil;

    _URL = [coder decodeObjectForKey:@"URL"];
    _HTMLURL = [coder decodeObjectForKey:@"HTMLURL"];
    _number = [coder decodeObjectForKey:@"number"];
    _state = [coder decodeUnsignedIntegerForKey:@"state"];
    _title = [coder decodeObjectForKey:@"title"];
    _body = [coder decodeObjectForKey:@"body"];
    _reporterLogin = [coder decodeObjectForKey:@"reporterLogin"];
    _assigneeLogin = [coder decodeObjectForKey:@"assigneeLogin"];
    _updatedAt = [coder decodeObjectForKey:@"updatedAt"];

    return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {
    if (self.URL != nil) [coder encodeObject:self.URL forKey:@"URL"];
    if (self.HTMLURL != nil) [coder encodeObject:self.HTMLURL forKey:@"HTMLURL"];
    if (self.number != nil) [coder encodeObject:self.number forKey:@"number"];
    if (self.title != nil) [coder encodeObject:self.title forKey:@"title"];
    if (self.body != nil) [coder encodeObject:self.body forKey:@"body"];
    if (self.reporterLogin != nil) [coder encodeObject:self.reporterLogin forKey:@"reporterLogin"];
    if (self.assigneeLogin != nil) [coder encodeObject:self.assigneeLogin forKey:@"assigneeLogin"];
    if (self.updatedAt != nil) [coder encodeObject:self.updatedAt forKey:@"updatedAt"];

    [coder encodeUnsignedInteger:self.state forKey:@"state"];
}

- (id)copyWithZone:(NSZone *)zone {
    GHIssue *issue = [[self.class allocWithZone:zone] init];
    issue->_URL = self.URL;
    issue->_HTMLURL = self.HTMLURL;
    issue->_number = self.number;
    issue->_state = self.state;
    issue->_reporterLogin = self.reporterLogin;
    issue->_assigneeLogin = self.assigneeLogin;
    issue->_updatedAt = self.updatedAt;

    issue.title = self.title;
    issue.body = self.body;
}

- (NSUInteger)hash {
    return self.number.hash;
}

- (BOOL)isEqual:(GHIssue *)issue {
    if (![issue isKindOfClass:GHIssue.class]) return NO;

    return [self.number isEqual:issue.number] && [self.title isEqual:issue.title] && [self.body isEqual:issue.body];
}

@end

Whew, that's a lot of boilerplate for something so simple! And, even then, there are some problems that this example doesn't address:

  • If the url or html_url field is missing, +[NSURL URLWithString:] will throw an exception.
  • There's no way to update a GHIssue with new data from the server.
  • There's no way to turn a GHIssue back into JSON.
  • GHIssueState shouldn't be encoded as-is. If the enum changes in the future, existing archives might break.
  • If the interface of GHIssue changes down the road, existing archives might break.

Why Not Use Core Data?

Core Data solves certain problems very well. If you need to execute complex queries across your data, handle a huge object graph with lots of relationships, or support undo and redo, Core Data is an excellent fit.

It does, however, come with some pain points:

  • Concurrency is a huge headache. It's particularly difficult to pass managed objects between threads. The NSManagedObjectContextConcurrencyTypes introduced in OS X 10.7 and iOS 5 don't really address this problem. Instead, object IDs have to be passed around and translated back and forth, which is highly inconvenient.
  • There's still a lot of boilerplate. Managed objects reduce some of the boilerplate seen above, but Core Data has plenty of its own. Correctly setting up a Core Data stack (with a persistent store and persistent store coordinator) and executing fetches can take many lines of code.
  • It's hard to get right. Even experienced developers can make mistakes when using Core Data, and the framework is not forgiving.

If you're just trying to access some JSON objects, Core Data can be a lot of work for little gain.

MTLModel

Enter MTLModel. This is what GHIssue looks like inheriting from MTLModel:

typedef enum : NSUInteger {
    GHIssueStateOpen,
    GHIssueStateClosed
} GHIssueState;

@interface GHIssue : MTLModel

@property (nonatomic, copy, readonly) NSURL *URL;
@property (nonatomic, copy, readonly) NSURL *HTMLURL;
@property (nonatomic, copy, readonly) NSNumber *number;
@property (nonatomic, assign, readonly) GHIssueState state;
@property (nonatomic, copy, readonly) NSString *reporterLogin;
@property (nonatomic, copy, readonly) NSString *assigneeLogin;
@property (nonatomic, copy, readonly) NSDate *updatedAt;

@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *body;

@end
@implementation GHIssue

+ (NSDateFormatter *)dateFormatter {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'Z'";
    return dateFormatter;
}

+ (NSDictionary *)externalRepresentationKeyPathsByPropertyKey {
    return [super.externalRepresentationKeyPathsByPropertyKey mtl_dictionaryByAddingEntriesFromDictionary:@{
        @"URL": @"url",
        @"HTMLURL": @"html_url",
        @"reporterLogin": @"user.login",
        @"assigneeLogin": @"assignee.login",
        @"updatedAt": @"updated_at"
    }];
}

+ (NSValueTransformer *)URLTransformer {
    return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName];
}

+ (NSValueTransformer *)HTMLURLTransformer {
    return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName];
}

+ (NSValueTransformer *)stateTransformer {
    NSDictionary *states = @{
        @"open": @(GHIssueStateOpen),
        @"closed": @(GHIssueStateClosed)
    };

    return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString *str) {
        return states[str];
    } reverseBlock:^(NSNumber *state) {
        return [states allKeysForObject:state].lastObject;
    }];
}

+ (NSValueTransformer *)updatedAtTransformer {
    return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString *str) {
        return [self.dateFormatter dateFromString:str];
    } reverseBlock:^(NSDate *date) {
        return [self.dateFormatter stringFromDate:date];
    }];
}

@end

Notably absent from this version are implementations of <NSCoding>, <NSCopying>, -isEqual:, and -hash. By inspecting the @property declarations you have in your subclass, MTLModel can provide default implementations for all these methods.

The problems with the original example all happen to be fixed as well:

  • If the url or html_url field is missing, +[NSURL URLWithString:] will throw an exception.

The URL transformer we used (included in Mantle) returns nil if given a nil string.

  • There's no way to update a GHIssue with new data from the server.

MTLModel has an extensible -mergeValuesForKeysFromModel: method, which makes it easy to specify how new model data should be integrated.

  • There's no way to turn a GHIssue back into JSON.
  • GHIssueState shouldn't be encoded as-is. If the enum changes in the future, existing archives might break.

Both of these issues are solved by using reversible transformers. -[GHIssue externalRepresentation] will return a JSON dictionary, which is also what gets encoded in -encodeWithCoder:. No saving fragile enum values!

  • If the interface of GHIssue changes down the road, existing archives might break.

MTLModel automatically saves the version of the model object that was used for archival. When unarchiving, +migrateExternalRepresentation:fromVersion: will be invoked if migration is needed, giving you a convenient hook to upgrade old data.

Other Extensions

Mantle also comes with miscellaneous cross-platform extensions meant to make your life easier, including:

There will assuredly be more, as we run into other common pain points!

Getting Involved

Mantle is still new and moving fast, so we may make breaking changes from time-to-time, but it has excellent unit test coverage and is already being used in GitHub for Mac's production code.

We heartily encourage you to check it out and file any issues that you find. If you'd like to contribute code, take a look at the README.

Enjoy!

October 22, 2012 kneath

Mark Otto is a GitHubber!

Today marks (heh) Mark Otto's first day as a Hubbernaut. You may recognize Mark as one half the Bootstrap team, the mastermind behind GitHub Buttons, or perhaps Big fan, love your work.

He'll be joining our team to help make everything GitHub sparkle, GitHub Enterprise doubly so. You can find him on the internets:

Welcome!

October 18, 2012 sundaykofax

Aden Beihl is a GitHubber!

Aden Beihl is the newest member of GitHub Support!

Aden is coming to the supportocats by way of kickball.com and Children's Memorial Hospital of Chicago. He's basically a fun saint. Having dealt with frustrated kickers, this job should be a breeze.

By rocking it in the Midwest, Aden will be getting to support requests sooner than his San Francisco sistren and brethren.

You can find him as Aden on GitHub.

October 18, 2012 foca

Buenos Aires Drinkup Tomorrow!

Join @calavera, @pengwynn, and all the lovely attendees from RubyConf Argentina for a beer or three at The Temple Bar in Buenos Aires, Argentina! Party starts this Friday 19th (tomorrow!) at 6pm!

The Facts

  • Where: The Temple Bar, Marcelo T. de Alvear 945, Buenos Aires.
  • When: Friday, October 19th, 6:00PM

October 15, 2012 shayfrendt

Jared Pace is a GitHubber!

Today marks Jared Pace's first day as a GitHubber. He hails from Durham, North Carolina, and we're stoked that he's bringing his Ruby skills to our Internal Tools team.

jared-pace

Jared also happens to be quite the sushi chef, enjoys bouncy castles, and knows how to BBQ some truly tasty North Carolina pulled pork.

Keep track of Jared on GitHub and Twitter!

Markdown Cheat Sheet

Format Text

Headers

# This is an <h1> tag
## This is an <h2> tag
###### This is an <h6> tag

Text styles

*This text will be italic*
_This will also be italic_
**This text will be bold**
__This will also be bold__

*You **can** combine them*

Lists

Unordered

* Item 1
* Item 2
  * Item 2a
  * Item 2b

Ordered

1. Item 1
2. Item 2
3. Item 3
   * Item 3a
   * Item 3b

Miscellaneous

Images

![GitHub Logo](/images/logo.png)
Format: ![Alt Text](url)

Links

http://github.com - automatic!
[GitHub](http://github.com)

Blockquotes

As Kanye West said:

> We're living the future so
> the present is our past.

Code Examples in Markdown

Syntax highlighting with GFM

```javascript
function fancyAlert(arg) {
  if(arg) {
    $.facebox({div:'#foo'})
  }
}
```

Or, indent your code 4 spaces

Here is a Python code example
without syntax highlighting:

    def foo:
      if not bar:
        return true

Inline code for comments

I think you should use an
`<addr>` element here instead.
Something went wrong with that request. Please try again.

Looking for the GitHub logo?