gitgit-bundle

Transferring changes made to multiple branches using git-bundle


I was looking for git-bundles as an option to keep my 2 repositories (being continuously worked on) in sync with each other.

Since both are two different geographical locations and setting up a VPN is also not an option I plan to use bundles..(Any other better alternative or method? )

I stumbled upon Jefromi's answer here . It explains things very well.

However if I have multiple branches being worked on and I wanted to update them all, how do I do it?

(The answer uses basis for master but uses --branches that will copy the complete history of all other branches in bundle again. I want only updated/added commits of all braches)


Solution

  • You can create a new backup while excluding what was in the previous backup:

    git fetch ../backup.bundle
    git bundle create ../newbackup.bundle ^backup/A ^backup/B A B C
    

    Here you create an incremental backup with incremental history for branches A and B, plus the new branch C.

    You can see that approach detailed in "Incremental backups with git bundle, for all branches"

    I prefer the simpler approach of using the date of the last backup:

    cd myRepo
    git bundle create mybundle-inc --since=10.days --all
    

    It is ok to backup "a bit more": duplicate commits won't be imported twice when you will use that incremental backup.

    I have made a script based on --since: save_bundles.


    With Git 2.31 (Q1 2021), "git bundle"(man) learns --stdin option to read its refs from the standard input.

    See commit 5bb0fd2, commit ce1d6d9, commit 9901164 (11 Jan 2021) by Jiang Xin (jiangxin).
    (Merged by Junio C Hamano -- gitster -- in commit 8b48981, 25 Jan 2021)

    bundle: arguments can be read from stdin

    Signed-off-by: Jiang Xin

    In order to create an incremental bundle, we need to pass many arguments to let git-bundle(man) ignore some already packed commits.
    It will be more convenient to pass args via stdin.
    But the current implementation does not allow us to do this.

    This is because args are parsed twice when creating bundle:

    • The first time for parsing args is in compute_and_write_prerequisites() by running git-rev-list command to write prerequisites in bundle file, and stdin is consumed in this step if "--stdin" option is provided for git-bundle.
    • Later nothing can be read from stdin when running setup_revisions() in create_bundle().

    The solution is to parse args once by removing the entire function compute_and_write_prerequisites() and then calling function setup_revisions().
    In order to write prerequisites for bundle, will call prepare_revision_walk() and traverse_commit_list().
    But after calling prepare_revision_walk(), the object array revs.pending is left empty, and the following steps could not work properly with the empty object array (revs.pending).
    Therefore, make a copy of revs to revs_copy for later use right after calling setup_revisions().

    The copy of revs_copy is not a deep copy, it shares the same objects with revs.
    The object array of revs has been cleared, but objects themselves are still kept.
    Flags of objects may change after calling prepare_revision_walk(), we can use these changed flags without calling the git rev-list(man) command and parsing its output like the former implementation.

    So for instance:

        # create bundle from stdin
        # input has a non-exist reference: "topic/deleted"
        cat >input <<-EOF &&
        ^topic/deleted
        ^$D
        ^topic/2
        EOF
    
        git bundle create stdin-2.bdl \
            --ignore-missing \
            --stdin \
            release <input
    

    With Git 2.41 (Q2 2023), "git bundle"(man) learned that - is a common way to say that the input comes from the standard input and/or the output goes to the standard output.

    It used to work only for output and only from the root level of the working tree.

    See commit 0bbe103, commit 7ce4088, commit ef3b291, commit bf8b1e0 (04 Mar 2023) by Jeff King (peff).
    See commit a8bfa99 (04 Mar 2023) by Junio C Hamano (gitster).
    (Merged by Junio C Hamano -- gitster -- in commit 95de376, 19 Mar 2023)

    bundle: let "-" mean stdin for reading operations

    Signed-off-by: Jeff King

    For writing, "bundle create -" indicates that the bundle should be written to stdout.
    But there's no matching handling of "-" for reading operations.
    This is inconsistent, and a little inflexible (though one can always use "/dev/stdin" on systems that support it).

    However, it's easy to change.
    Once upon a time, the bundle-reading code required a seekable descriptor, but that was fixed long ago in e9ee84c ("bundle: allowing to read from an unseekable fd", 2011-10-13, Git v1.7.8-rc0 -- merge).
    So we just need to handle "-" explicitly when opening the file.

    We could do this by handling "-" in read_bundle_header(), which the reading functions all call already.
    But that is probably a bad idea.
    It's also used by low-level code like the transport functions, and we may want to be more careful there.
    We do not know that stdin is even available to us, and certainly we would not want to get confused by a configured URL that happens to point to "-".

    So instead, let's add a helper to builtin/bundle.c.
    Since both the bundle code and some of the callers refer to the bundle by name for error messages, let's use the string "<stdin>" to make the output a bit nicer to read.

    This applies to git bundle: