Predict how much data will be pushed in a git push

2019-01-11 13:20发布

问题:

I am occasionally on an expensive Internet connection and I would like to know (at least approximately) how much data will be pushed to the remote in a git push.

回答1:

Actually, I think I like my comment enough to post it as an answer!

When you push, git creates a pack of all the necessary objects and uploads that to the remote. This means we're looking for a way to predict that pack size. Since the packs are compressed, that makes it very difficult to do anything based on diffs or object sizes; what we really want to do is just see how big that pack will be. It'd be nice if you could interrupt the push, just after it's constructed the pack, and decide to proceed based on the pack size, but I don't think that's possible. My best guess is to try to recreate the pack that would be pushed and inspect that.

A bundle file is basically a pack with header information (have a look at the source if you like). This means it's a convenient porcelain command that'll create a file with the size you care about. (Much easier than trying to use pack-objects manually.) Use something like this:

git bundle create foo.bundle ^origin/master master

That'll give you a bundle containing everything needed to get to master, given that the remote has origin/master - exactly the same thing that should be pushed by git push origin master. If you have additional branches you'll be pushing, you can tack them on as well; it's just taking rev-list args:

git bundle create foo.bundle ^origin/master master ^origin/topic topic ...

Just check the size of that created bundle; it should be nearly equivalent to what you'll end up pushing. This does mean that you'll end up having to create the pack twice (once with the bundle and once with the push), but unless this is a really big push which takes a long time to pack up, that shouldn't be a huge problem.



回答2:

You can find out pretty much exactly by running a similar bit of Bash to what Git will run internally when it creates the pack file to push:

$ echo $(git merge-base HEAD origin/master)..HEAD | git pack-objects --revs --thin --stdout -q | wc -c

This should output the byte-count of the pack file Git would send. Broken down:

# Find the common ancestor of HEAD and origin/master, and output a
# revision range (<a>..<b>) string to git pack-objects.
echo $(git merge-base HEAD origin/master)..HEAD

# Generate the pack file containing the revision range specified above, writing
# it to stdout.
git pack-objects --revs --thin --stdout -q

# Print the byte count of the file contents passed via stdin.
wc -c

This is conditional on doing a git fetch right before you push; if you don't, Git won't be able to find the common ancestor and will send the contents of your entire repository. See this answer for more info.



回答3:

git diff HEAD origin/master --stat