json не может быть лучшим выбором для форматов на диске; Проблема, связанная с добавлением данных, является хорошим примером того, почему это может быть. В частности, объекты json имеют синтаксис, который означает, что весь объект должен быть прочитан и проанализирован, чтобы понять любую его часть.
К счастью, есть много других вариантов. Особенно простой - CSV; который хорошо поддерживается стандартной библиотекой python. Самым большим недостатком является то, что он хорошо работает только для текста; он требует дополнительных действий со стороны программиста для преобразования значений в числа или другие форматы, если это необходимо.
Другой вариант, который не имеет этого ограничения, заключается в использовании базы данных sqlite, которая также имеет встроенную базу данных, в поддержке в python. Это, вероятно, будет большим отступлением от кода, который у вас уже есть, но он более естественно поддерживает модель «изменить немного», которую вы, по-видимому, пытаетесь построить.
Поведение, которое вы описываете для pull --all
, точно так, как ожидалось, хотя и не обязательно полезно. Опция передается по git fetch, которая затем извлекает все ссылки из всех пультов, а не только необходимые; pull
затем объединяет (или в вашем случае, переустанавливает) соответствующую отдельную ветвь.
Если вы хотите проверить другие ветви, вам придется проверить их. И да, для слияния (и rebasing) абсолютно требуется дерево работы, поэтому они не могут быть выполнены без проверки других ветвей. Вы можете завершить свои описанные шаги в сценарий / псевдоним, если хотите, хотя я бы предложил присоединиться к командам с &&
, чтобы один из них потерпел неудачу, он не будет пытаться вспахивать.
Эта проблема еще не решена (по крайней мере), по крайней мере, нелегко / без скриптов: см. этот пост в списке рассылки git от Junio C Hamano, объясняя ситуацию и предоставляя вызов для простого решения.
Основная причина состоит в том, что вам не нужно это:
С git, который не является древним (т.е. v1.5.0 или новее), нет причин иметь локальные " dev ", которые полностью отслеживают дистанцию. Если вы хотите только посмотреть и посмотреть, вы можете проверить ветвь удаленного отслеживания непосредственно на отдельном HEAD с помощью «
git checkout origin/dev
».Это означает, что единственные случаи, которые нам нужно сделать удобно для пользователей обрабатывать эти локальные ветви, которые «отслеживают» удаленные, когда у вас есть локальные изменения, или когда вы планируете их использовать.
Если у вас есть локальные изменения на «dev», которые отмеченный для отслеживания удаления «dev», и если вы находитесь на ветке, отличной от «dev», тогда мы ничего не должны делать после того, как «
blockquote>git fetch
» обновит «dev» удаленного отслеживания. В любом случае он не будет ускоренным переадресацией. Призыв к решению заключался в том, что для опции или внешнего скрипта необходимо обрезать локальные ветви, которые следуют за ветками удаленного отслеживания, а не поддерживать их до -date путем быстрой пересылки, как и запрошенный оригинальный плакат.
Итак, как насчет «
git branch --prune --remote=<upstream>
», который итерации по локальным ветвям, и если(1) а не текущая ветвь; и (2) он отмечен для отслеживания некоторой ветви, взятой из & lt; upstream & gt ;; и (3) он не имеет никаких коммитов по своему усмотрению;
затем удаляет эту ветвь? «
blockquote>git remote --prune-local-forks <upstream>
» также прекрасен; Меня не волнует, какая команда очень сильно реализует эту функцию.Примечание: с git 2.10 такого решения не существует. Обратите внимание, что подкоманда
git remote prune
иgit fetch --prune
относятся к удалению ветви удаленного отслеживания для ветки, которая больше не существует на удаленном компьютере, а не об удалении локальной ветви, которая отслеживает ветку удаленного отслеживания (для которой ветвь удаленного отслеживания является ветвью вверх по течению) .
Просто отправьте обновленный ответ. git-up
больше не поддерживается, и если вы читаете документацию, они упоминают, что функциональность теперь доступна в git .
Начиная с Git 2.9, git pull - rebad -autostash делает в основном то же самое.
Соответственно, если вы обновляете Git 2.9 или новее, вы можете использовать этот псевдоним вместо установки git-up:
blockquote>
git config --global alias.up 'pull --rebase --autostash'
Вы также можете установить это для каждого
git pull
по Git 2.9 (спасибо @VonC, см. его ответ здесь )git config --global pull.rebase true git config --global rebase.autoStash true
git-up
, потому что они не упоминают, что
– aug
5 September 2017 в 21:03
git-up
.
– ray
2 November 2017 в 20:40
Чтобы ответить на этот вопрос Мэттом Коннолли, это более безопасный способ обновить локальные ссылки, которые можно быстро перенаправить, не проверяя ветвь. Он не обновляет ветви, которые не могут быть быстро перенаправлены (т. Е. Расходились), и не обновляет ветвь, которая в настоящее время проверена (потому что тогда рабочая копия также должна быть обновлена).
git fetch
head="$(git symbolic-ref HEAD)"
git for-each-ref --format="%(refname) %(upstream)" refs/heads | while read ref up; do
if [ -n "$up" -a "$ref" != "$head" ]; then
mine="$(git rev-parse "$ref")"
theirs="$(git rev-parse "$up")"
base="$(git merge-base "$ref" "$up")"
if [ "$mine" != "$theirs" -a "$mine" == "$base" ]; then
git update-ref "$ref" "$theirs"
fi
fi
done
Вот хороший ответ: Как получить все ветви git
for remote in `git branch -r`; do git branch --track $remote; done
git pull --all
git fetch
и git pull
, а не просто git pull
?
– syntagma
20 August 2015 в 14:15
origin/
– Yassine El Badaoui
17 October 2017 в 09:42
Это не так сложно автоматизировать:
#!/bin/sh
# Usage: fetchall.sh branch ...
set -x
git fetch --all
for branch in "$@"; do
git checkout "$branch" || exit 1
git rebase "origin/$branch" || exit 1
done
git rebase origin/$branch
на git pull
, чтобы он извлекался из соответствующей ветви отслеживания (предположительно по началу) и слияния или переустановки, как определено конфигурацией.
– Cascabel
30 November 2010 в 22:06
fetch
. Редактировал; дополнительные функции / исправления независимо от OP.
– Fred Foo
30 November 2010 в 23:18
pull
(или проверить branch.<branch>.rebase
), чтобы вы случайно не переустанавливали ветвь, которая настроена на нормальное выключение (слияние).
– Cascabel
30 November 2010 в 23:54
set -e
вместо || exit 1
, чтобы сделать вывод интерпретатора первой ошибкой.
– crishoj
2 May 2018 в 11:32
Если refs / heads / master может быть быстро перенаправлен на refs / remotes / foo / master, вывод
git merge-base refs/heads/master refs/remotes/foo/master
должен вернуть идентификатор SHA1, который ссылается на / heads / master points. С этим вы можете собрать скрипт, который автоматически обновляет все локальные ветви, у которых не было никаких отвлекающих коммитов.
Этот маленький скрипт оболочки (я назвал его git-can-ff) иллюстрирует, как он может
#!/bin/sh
set -x
usage() {
echo "usage: $(basename $0) <from-ref> <to-ref>" >&2
exit 2
}
[ $# -ne 2 ] && usage
FROM_REF=$1
TO_REF=$2
FROM_HASH=$(git show-ref --hash $FROM_REF)
TO_HASH=$(git show-ref --hash $TO_REF)
BASE_HASH=$(git merge-base $FROM_REF $TO_REF)
if [ "$BASE_HASH" = "$FROM_HASH" -o \
"$BASE_HASH" = "$FROM_REF" ]; then
exit 0
else
exit 1
fi
Я использую подкоманду sync
hub для автоматизации этого. Хаб псевдонимов как git
, поэтому введите команду:
git sync
Это обновляет все локальные ветви, имеющие соответствующую ветку вверх по течению. На странице man:
blockquote>
- Если локальная ветка устарела, перетащите ее вперед,
- Если локальная ветка содержит непроверенную работу, предупредите об этом; / g4]
- Если ветка кажется объединенной, и ее ветвь восходящего потока была удалена, удалите ее.
Он также обрабатывает фиксированные / неработающие незафиксированные изменения в текущей ветке.
Я использовал подобный инструмент под названием git-up , но он больше не поддерживается, а
git sync
выполняет почти то же самое.
git config --global git-up.rebase.auto false
.
– Dan Loewenherz
16 July 2015 в 21:41
Это все еще не автоматическое, так как я хочу, чтобы была опция - и должна быть какая-то проверка, чтобы убедиться, что это может произойти только для быстрых обновлений (поэтому вручную делать притяжение намного безопаснее! !), но предостережения в стороне вы можете:
git fetch origin
git update-ref refs/heads/other-branch origin/other-branch
обновить позицию вашего локального отделения, не проверяя его.
Примечание: вы потеряете свою текущую ветку положение и перемещение его туда, где находится ветвь происхождения, а это означает, что если вам нужно слить, вы потеряете данные!
Здесь есть много приемлемых ответов, но некоторые из сантехники могут быть немного непрозрачными для непосвященных. Вот еще более простой пример, который можно легко настроить:
$ cat ~/bin/git/git-update-all
#!/bin/bash
# Update all local branches, checking out each branch in succession.
# Eventually returns to the original branch. Use "-n" for dry-run.
git_update_all() {
local run br
br=$(git name-rev --name-only HEAD 2>/dev/null)
[ "$1" = "-n" ] && shift && run=echo
for x in $( git branch | cut -c3- ) ; do
$run git checkout $x && $run git pull --ff-only || return 2
done
[ ${#br} -gt 0 ] && $run git checkout "$br"
}
git_update_all "$@"
Если вы добавите ~/bin/git
в свой PATH
(при условии, что файл ~/bin/git/git-update-all
), вы можете просто запустить:
$ git update-all
Добавьте этот скрипт в .profile
в Mac OS X:
# Usage:
# `git-pull-all` to pull all your local branches from origin
# `git-pull-all remote` to pull all your local branches from a named remote
function git-pull-all() {
START=$(git symbolic-ref --short -q HEAD);
for branch in $(git branch | sed 's/^.//'); do
git checkout $branch;
git pull ${1:-origin} $branch || break;
done;
git checkout $START;
};
function git-push-all() {
git push --all ${1:-origin};
};
Примечание. Несмотря на то, что я разместил собственное решение, я бы рекомендовал использовать git-up , что также является принятым ответом.
Я знаю, что этот вопрос почти 3 года, но я задал себе тот же вопрос и не нашел готового решения. Итак, я создал собственный скрипт командной оболочки git.
Здесь он идет, скрипт git-ffwd-update
делает следующее ...
git remote update
, чтобы получить значения lates revs git remote show
, чтобы получить список локальных ветвей, отслеживающих удаленную ветвь (например, ветви, которые могут использоваться с git pull
) git rev-list --count <REMOTE_BRANCH>..<LOCAL_BRANCH>
, сколько из них фиксирует локальную ветвь за пультом (и наоборот наоборот) git branch -l -f <LOCAL_BRANCH> -t <REMOTE_BRANCH>
скрипт можно вызвать как:
$ git ffwd-update
Fetching origin
branch bigcouch was 10 commit(s) behind of origin/bigcouch. reseting local branch to remote
branch develop was 3 commit(s) behind of origin/develop. reseting local branch to remote
branch master is 6 commit(s) behind and 1 commit(s) ahead of origin/master. could not be fast-forwarded
Полный скрипт должен быть сохранен как git-ffwd-update
и должен находиться на PATH
.
#!/bin/bash
main() {
REMOTES="$@";
if [ -z "$REMOTES" ]; then
REMOTES=$(git remote);
fi
REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
CLB=$(git branch -l|awk '/^\*/{print $2}');
echo "$REMOTES" | while read REMOTE; do
git remote update $REMOTE
git remote show $REMOTE -n \
| awk '/merges with remote/{print $5" "$1}' \
| while read line; do
RB=$(echo "$line"|cut -f1 -d" ");
ARB="refs/remotes/$REMOTE/$RB";
LB=$(echo "$line"|cut -f2 -d" ");
ALB="refs/heads/$LB";
NBEHIND=$(( $(git rev-list --count $ALB..$ARB 2>/dev/null) +0));
NAHEAD=$(( $(git rev-list --count $ARB..$ALB 2>/dev/null) +0));
if [ "$NBEHIND" -gt 0 ]; then
if [ "$NAHEAD" -gt 0 ]; then
echo " branch $LB is $NBEHIND commit(s) behind and $NAHEAD commit(s) ahead of $REMOTE/$RB. could not be fast-forwarded";
elif [ "$LB" = "$CLB" ]; then
echo " branch $LB was $NBEHIND commit(s) behind of $REMOTE/$RB. fast-forward merge";
git merge -q $ARB;
else
echo " branch $LB was $NBEHIND commit(s) behind of $REMOTE/$RB. reseting local branch to remote";
git branch -l -f $LB -t $ARB >/dev/null;
fi
fi
done
done
}
main $@
Начиная с git 2.9:
git pull --rebase --autostash
См. https://git-scm.com/docs/git-rebase
Автоматически создавать временный тайник перед началом операции и применять его после завершения операции. Это означает, что вы можете запустить rebase на грязной worktree. Тем не менее, используйте с осторожностью: окончательное приложение с приложением после успешной перезагрузки может привести к нетривиальным конфликтам.
blockquote>
Сценарий, который я написал для моего GitBash . Выполняет следующее:
git checkout branch
git pull origin
** Я использую это, но не тестировал полностью, используйте на свой страх и риск. Пример этого скрипта в файле .bash_alias здесь .
# Do a pull on all branches that are tracking a remote branches, will from origin by default.
# If current branch is dirty, will stash changes and reply after pull.
# Usage: pullall [remoteName]
alias pullall=pullAll
function pullAll (){
# if -h then show help
if [[ $1 == '-h' ]]
then
echo "Description: Pulls new changes from upstream on all branches that are tracking remotes."
echo
echo "Usage: "
echo "- Default: pullall"
echo "- Specify upstream to pull from: pullall [upstreamName]"
echo "- Help: pull-all -h"
else
# default remote to origin
remote="origin"
if [ $1 != "" ]
then
remote=$1
fi
# list all branches that are tracking remote
# git branch -vv : list branches with their upstreams
# grep origin : keep only items that have upstream of origin
# sed "s/^.."... : remove leading *
# sed "s/^"..... : remove leading white spaces
# cut -d" "..... : cut on spaces, take first item
# cut -d splits on space, -f1 grabs first item
branches=($(git branch -vv | grep $remote | sed "s/^[ *]*//" | sed "s/^[ /t]*//" | cut -d" " -f1))
# get starting branch name
startingBranch=$(git rev-parse --abbrev-ref HEAD)
# get starting stash size
startingStashSize=$(git stash list | wc -l)
echo "Saving starting branch state: $startingBranch"
git stash
# get the new stash size
newStashSize=$(git stash list | wc -l)
# for each branch in the array of remote tracking branches
for branch in ${branches[*]}
do
echo "Switching to $branch"
git checkout $branch
echo "Pulling $remote"
git pull $remote
done
echo "Switching back to $startingBranch"
git checkout $startingBranch
# compare before and after stash size to see if anything was stashed
if [ "$startingStashSize" -lt "$newStashSize" ]
then
echo "Restoring branch state"
git stash pop
fi
fi
}
Здесь много ответов, но никто не использует git-fetch
для непосредственного обновления локального рефлекса, что намного проще, чем проверка ветвей, и более безопасная, чем git-update-ref
.
Здесь мы используйте git-fetch
для обновления не текущих ветвей и git pull --ff-only
для текущей ветви. Это:
, и вот он:
#!/bin/bash
currentbranchref="$(git symbolic-ref HEAD 2>&-)"
git branch -r | grep -v ' -> ' | while read remotebranch
do
# Split <remote>/<branch> into remote and branchref parts
remote="${remotebranch%%/*}"
branchref="refs/heads/${remotebranch#*/}"
if [ "$branchref" == "$currentbranchref" ]
then
echo "Updating current branch $branchref from $remote..."
git pull --ff-only
else
echo "Updating non-current ref $branchref from $remote..."
git fetch "$remote" "$branchref:$branchref"
fi
done
Из справочной страницы для git-fetch
:
<refspec>
The format of a <refspec> parameter is an optional plus +, followed by the source ref <src>,
followed by a colon :, followed by the destination ref <dst>.
The remote ref that matches <src> is fetched, and if <dst> is not empty string, the local ref
that matches it is fast-forwarded using <src>. If the optional plus + is used, the local ref is
updated even if it does not result in a fast-forward update.
Указывая git fetch <remote> <ref>:<ref>
(без каких-либо +
), мы получаем выборку, которая обновляет локальный рефер, только когда его можно быстро пересылать.
Примечание: это предполагает, что локальная и удаленная ветви называются одинаковыми (и что вы хотите отслеживать все ветви), он должен действительно использовать информацию о том, какие локальные филиалы у вас есть и что они настроены для отслеживания.
c*n
(вместо 1), где c
- некоторое количество повторяющихся команд, а n
- количество ветвей.
– jww
21 May 2016 в 01:04
git branch -r | grep -v ' -> ' | while read remotebranch
на git branch -r | grep -v ' -> ' | grep -f <(git branch | cut -c 3- | awk '{print "\\S*/"$0"$"}') | while read remotebranch
, чтобы ограничить ее ветвями, которые у меня уже есть локально. Также я добавил git fetch --prune
в начале, чтобы обновить список удаленных филиалов, прежде чем что-либо делать, что позволяет избежать некоторых предупреждений.
– Nate Cook
19 March 2018 в 20:17
Немного другой скрипт, который только быстрые переходы, имена которых совпадают с их ветвью вверх по течению. Он также обновляет текущую ветвь, если возможна быстрая перемотка вперед.
Убедитесь, что все ветви ветвей ваших ветвей установлены правильно, запустив git branch -vv
. Установите верхнюю ветвь с помощью git branch -u origin/yourbanchname
Скопируйте пасту в файл и chmod 755:
#!/bin/sh
curbranch=$(git rev-parse --abbrev-ref HEAD)
for branch in $(git for-each-ref refs/heads --format="%(refname:short)"); do
upbranch=$(git config --get branch.$branch.merge | sed 's:refs/heads/::');
if [ "$branch" = "$upbranch" ]; then
if [ "$branch" = "$curbranch" ]; then
echo Fast forwarding current branch $curbranch
git merge --ff-only origin/$upbranch
else
echo Fast forwarding $branch with origin/$upbranch
git fetch . origin/$upbranch:$branch
fi
fi
done;
Сценарий из @larsmans немного улучшился:
#!/bin/sh
set -x
CURRENT=`git rev-parse --abbrev-ref HEAD`
git fetch --all
for branch in "$@"; do
if ["$branch" -ne "$CURRENT"]; then
git checkout "$branch" || exit 1
git rebase "origin/$branch" || exit 1
fi
done
git checkout "$CURRENT" || exit 1
git rebase "origin/$CURRENT" || exit 1
После завершения работы, рабочая копия удаляется из той же ветви, что и до вызова сценария.
Версия git pull
:
#!/bin/sh
set -x
CURRENT=`git rev-parse --abbrev-ref HEAD`
git fetch --all
for branch in "$@"; do
if ["$branch" -ne "$CURRENT"]; then
git checkout "$branch" || exit 1
git pull || exit 1
fi
done
git checkout "$CURRENT" || exit 1
git pull || exit 1
Если вы находитесь в Windows, вы можете использовать PyGitUp , который является клоном git-up
для Python. Вы можете установить его с помощью pip с помощью pip install --user git-up
или через Scoop , используя scoop install git-up
[ [/g3]
Похоже, что многие другие внесли аналогичные решения, но я думал, что разделю то, что я придумал, и пригласить других вносить свой вклад. Это решение имеет приятный красочный выход, изящно обрабатывает ваш текущий рабочий каталог и быстро, потому что он не делает никаких проверок и оставляет ваш рабочий каталог в такт. Кроме того, это всего лишь сценарий оболочки без зависимостей, кроме git. (только проверено на OSX до сих пор)
#!/usr/bin/env bash
gitup(){
RED='\033[33;31m'
YELLO='\033[33;33m'
GREEN='\033[33;32m'
NC='\033[0m' # No Color
HEAD=$(git rev-parse HEAD)
CHANGED=$(git status --porcelain | wc -l)
echo "Fetching..."
git fetch --all --prune &>/dev/null
for branch in `git for-each-ref --format='%(refname:short)' refs/heads`; do
LOCAL=$(git rev-parse --quiet --verify $branch)
if [ "$HEAD" = "$LOCAL" ] && [ $CHANGED -gt 0 ]; then
echo -e "${YELLO}WORKING${NC}\t\t$branch"
elif git rev-parse --verify --quiet $branch@{u}&>/dev/null; then
REMOTE=$(git rev-parse --quiet --verify $branch@{u})
BASE=$(git merge-base $branch $branch@{u})
if [ "$LOCAL" = "$REMOTE" ]; then
echo -e "${GREEN}OK${NC}\t\t$branch"
elif [ "$LOCAL" = "$BASE" ]; then
if [ "$HEAD" = "$LOCAL" ]; then
git merge $REMOTE&>/dev/null
else
git branch -f $branch $REMOTE
fi
echo -e "${GREEN}UPDATED${NC}\t\t$branch"
elif [ "$REMOTE" = "$BASE" ]; then
echo -e "${RED}AHEAD${NC}\t\t$branch"
else
echo -e "${RED}DIVERGED${NC}\t\t$branch"
fi
else
echo -e "${RED}NO REMOTE${NC}\t$branch"
fi
done
}
https://github.com/davestimpert/gitup
Извините, я тоже, похоже, пришел с тем же именем, что и другой инструмент выше.
Это можно сделать, используя следующий скрипт ... Сначала он будет извлекать все ветви и проверку по одному и обновлять сам по себе.
#!/bin/bash
git branch -r | grep -v '\->' | while read remote; do git branch --track
"${remote#origin/}" "$remote"; done
set -x
CURRENT=`git rev-parse --abbrev-ref HEAD`
git fetch --all
branch_name=$(git branch | awk '{print $1" "}' | grep -v '*' | xargs)
for branch in $branch_name; do
git checkout "$branch" || exit 1
git rebase "origin/$branch" || exit 1
git pull origin $branch|| exit 1
done
git checkout "$CURRENT" || exit 1
git pull || exit 1