Tag Archives: git

Resolving the git error “pack exceeds maximum allowed size” during push

Elephant_near_ndutuI have a large repository that takes up a modest number of gigabytes. When attempting to push it to a  new remote repository,  the push failed, complaining that the pack size exceeds the maximum allowed.

First of all, let’s get out of the way the fact that repacking the local repository or fiddling with the pack.packSizeLimit limit configuration setting won’t fix the problem. That will simply tidy  up your local machine.

As I understand it (corrections welcome), the problem is a collision of several things. When performing this massive beginning-to-end push, git creates a massive pack on  the fly and pipes that across the network to the remote machine. The remote machine needs  to be able to perform memory mapping on this huge wad of data. File system, CPU architecture, and memory needs have to be satisfied for this to work. Otherwise, the pack size error is reported and the push fails. Annoyingly, this can happen after you’ve transferred gigabytes of data across a network with a bottleneck, completely wasting a lot of time.

Fortunately the work-around is simple. Push the repository in chunks, working your way up the tree.

If your repository has a lot of branching, you may be able to push a branch at a time, as the generated pack will be for that branch.

This repo of mine has a very linear history, and feeling a little lazy I used my git GUI (SourceTree) to make a temporary branch about a third way up the tree, and pushed that. I moved the temporary branch another third of the way up the tree, and pushed that. Finally I could push master and remove the temporary branch.

If the repository were big and hairy enough one could write a script to traverse the tree and programmatically push at appropriate commit points, but for me it’s an exceptional situation that doesn’t warrant that type of effort.


Reverting File Changes With git

This is not obvious to those of us with lingering Subversion habits comprar viagra madrid. If you’ve edited a file and simply want to discard its changes (à la Subversion’s revert), use:

git checkout filename

If it so happens that your file name is the same as a branch, you’ll need to use:

git checkout -- filename

Use the Right Tool for the Job

You may be tempted to use git reset --hard, but that will reset all uncommitted changes. If you just want to undo the changes to a single file, that’s the wrong tool.


How to Extract a Subdirectory as a New git Repository

Some time ago I converted a massive Subversion repository to git. It’s largely legacy projects that are in storage. I’ve been asked to update one project, and felt it would be best to split that project out into its own git repository.

I was able to find an excellent treatment on stackoverflow here. The following are my notes and observations.

  1. Clone the local repository.
    git clone monster-repository project-repository
    cd project-repository

    This creates a working copy that will be manipulated.

  2. In this particular case, I was not interested in any branches other than master.
  3. Disconnect the new repository from the old origin
    git remote rm origin
  4. In this particular case, I was not interested in preserving the tags, especially the one generated during the Subversion to git conversion. This removes all tags.
    git tag -l | xargs git tag -d
  5. This is a cool command. It removes everything except the desired subdirectory, and moves the subdirectory up to the project root directory. In this example, project-directory is the name of the subdirectory for the project that we’re extracting and want to move to the relative root.
    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter project-directory HEAD
  6. This purges the repository of all unrelated commits and shrinks the repository.
    git reset --hard
    git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
    git reflog expire --expire=now --all
    git gc --aggressive --prune=now
  7. Finally, connect this repository to the new remote, and populate the new remote repository.
    git remote add origin [url]
    git push origin master

I didn’t want to purge the project from the original legacy repository, so I simply deleted the entire project directory, and committed with the message “This directory has been moved to its own git repository found at [url].”.

Installing gitolite on a Mac

I’ve come to love gitolite for hosting private git repositories. It’s very easy to administer and trouble-free.

On one project, I needed to share a very large git repository between two virtual machines. I didn’t want the overhead of using a private git repository out on the Internet, just something local, like my workstation that runs OS X.

I used the System Preferences to create an account named git, and followed the gitolite install instructions.

I ran into a couple of problems that were easily resolved.

Path for Installer

First, to address gitolite complaining about not being able to find itself, I created a .bash_profile with the following:

[bash light=”true”]
export PATH=/Users/git/bin:$PATH

Now I could run the gitolite install cleanly. I would recommend doing this first thing after creating the git account to host gitolite.

Help gitolite Find git

I installed git from the link on the front page of the git web site. This installs git in /usr/local/git/bin, which gitolite doesn’t like out of the box. The fix is easy. When gitolite installs, it brings up the config file (~/.gitolite.rc) in an editor for you to tweak.

Find the line

[bash light=”true”]

and change it to

[bash light=”true”]

This will prevent error messages such as

[bash light=”true”]
$ ssh git@localhost
PTY allocation request failed on channel 0
Can’t exec “git”: No such file or directory at /Users/git/bin/gitolite.pm line 562.
Use of uninitialized value $git_version in substitution (s///) at /Users/git/bin/gitolite.pm line 563.
hello Yourkey, this is gitolite v2.2-4-the gitolite config gives you the following access:
Use of uninitialized value $git_version in concatenation (.) or string at /Users/git/bin/gitolite.pm line 564.
R W gitolite-admin
@R_ @W_ testing
Connection to localhost closed.

from appearing and preventing gitolite from working.

Update 1 September 2013

These instructions seem to still work with gitolite 3, with additional commentary:

If you ssh into your OS X machine, you might see the message:

[bash light=”true”]
$ ssh git@localhost
PTY allocation request failed on channel 0

gitolite is still working. There is simply a collision between ssh versions. You an get a list of the repositories you’re allowed to access by one of these two commands:

[bash light=”true”]
$ ssh -T git@localhost
$ ssh git@localhost info

git Over A Non-Standard ssh Port

git speaks ssh over the standard port 22 out of the box, and flawlessly. For example:

git clone git@hostname:repository_name

There are a fair number of installations running ssh on non-standard ports, however, and the above method doesn’t directly support a port, it seem. Linux Torvald answered the the question back in 2005, and suggested editing the local ssh config file. This works beautifully where Un*x is spoken, including Mac OS X.

In the ~/.ssh/config file add an entry such as:

Host host_alias
    User git
    Port port_number
    Hostname hostname

For those poor souls in Windows land, Mauvis Ledford has a tip:

$ git clone ssh://user@host:port/repository

should work also.