What are the differences between git remote prune, git prune, git fetch --prune, etc

前端 未结 4 1967
野趣味
野趣味 2020-11-27 09:06

My situation is this... someone working on the same repo has deleted a branch from his local & remote repo...

Most people who have asked about this kind of probl

相关标签:
4条回答
  • 2020-11-27 09:17

    I don't blame you for getting frustrated about this. The best way to look at is this. There are potentially three versions of every remote branch:

    1. The actual branch on the remote repository
      (e.g., remote repo at https://example.com/repo.git, refs/heads/master)
    2. Your snapshot of that branch locally (stored under refs/remotes/...)
      (e.g., local repo, refs/remotes/origin/master)
    3. And a local branch that might be tracking the remote branch
      (e.g., local repo, refs/heads/master)

    Let's start with git prune. This removes objects that are no longer being referenced, it does not remove references. In your case, you have a local branch. That means there's a ref named random_branch_I_want_deleted that refers to some objects that represent the history of that branch. So, by definition, git prune will not remove random_branch_I_want_deleted. Really, git prune is a way to delete data that has accumulated in Git but is not being referenced by anything. In general, it doesn't affect your view of any branches.

    git remote prune origin and git fetch --prune both operate on references under refs/remotes/... (I'll refer to these as remote references). It doesn't affect local branches. The git remote version is useful if you only want to remove remote references under a particular remote. Otherwise, the two do exactly the same thing. So, in short, git remote prune and git fetch --prune operate on number 2 above. For example, if you deleted a branch using the git web GUI and don't want it to show up in your local branch list anymore (git branch -r), then this is the command you should use.

    To remove a local branch, you should use git branch -d (or -D if it's not merged anywhere). FWIW, there is no git command to automatically remove the local tracking branches if a remote branch disappears.

    0 讨论(0)
  • 2020-11-27 09:18

    In the event that anyone would be interested. Here's a quick shell script that will remove all local branches that aren't tracked remotely. A word of caution: This will get rid of any branch that isn't tracked remotely regardless of whether it was merged or not.

    If you guys see any issues with this please let me know and I'll fix it (etc. etc.)

    Save it in a file called git-rm-ntb (call it whatever) on PATH and run:

    git-rm-ntb <remote1:optional> <remote2:optional> ...

    clean()
    {
      REMOTES="$@";
      if [ -z "$REMOTES" ]; then
        REMOTES=$(git remote);
      fi
      REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
      RBRANCHES=()
      while read REMOTE; do
        CURRBRANCHES=($(git ls-remote $REMOTE | awk '{print $2}' | grep 'refs/heads/' | sed 's:refs/heads/::'))
        RBRANCHES=("${CURRBRANCHES[@]}" "${RBRANCHES[@]}")
      done < <(echo "$REMOTES" )
      [[ $RBRANCHES ]] || exit
      LBRANCHES=($(git branch | sed 's:\*::' | awk '{print $1}'))
      for i in "${LBRANCHES[@]}"; do
        skip=
        for j in "${RBRANCHES[@]}"; do
          [[ $i == $j ]] && { skip=1; echo -e "\033[32m Keeping $i \033[0m"; break; }
        done
        [[ -n $skip ]] || { echo -e "\033[31m $(git branch -D $i) \033[0m"; }
      done
    }
    
    clean $@
    
    0 讨论(0)
  • 2020-11-27 09:19

    git remote prune and git fetch --prune do the same thing: deleting the refs to the branches that don't exist on the remote, as you said. The second command connects to the remote and fetches its current branches before pruning.

    However it doesn't touch the local branches you have checked out, that you can simply delete with

    git branch -d  random_branch_I_want_deleted
    

    Replace -d by -D if the branch is not merged elsewhere

    git prune does something different, it purges unreachable objects, those commits that aren't reachable in any branch or tag, and thus not needed anymore.

    0 讨论(0)
  • 2020-11-27 09:19

    Note that one difference between git remote --prune and git fetch --prune is being fixed, with commit 10a6cc8, by Tom Miller (tmiller) (for git 1.9/2.0, Q1 2014):

    When we have a remote-tracking branch named "frotz/nitfol" from a previous fetch, and the upstream now has a branch named "**frotz"**, fetch would fail to remove "frotz/nitfol" with a "git fetch --prune" from the upstream.
    git would inform the user to use "git remote prune" to fix the problem.

    So: when a upstream repo has a branch ("frotz") with the same name as a branch hierarchy ("frotz/xxx", a possible branch naming convention), git remote --prune was succeeding (in cleaning up the remote tracking branch from your repo), but git fetch --prune was failing.

    Not anymore:

    Change the way "fetch --prune" works by moving the pruning operation before the fetching operation.
    This way, instead of warning the user of a conflict, it automatically fixes it.

    0 讨论(0)
提交回复
热议问题