Как я могу выполнить проверки перед фиксацией git только для поэтапного контента?

Предположим, git status дает это:

# On branch X
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   file1.cc
#   modified:   file1.h
#   modified:   file1_test.cc
#   modified:   SConscript
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#   (commit or discard the untracked or modified content in submodules)
#
#   modified:   file1.cc
#   modified:   tinyxml2 (untracked content)
#

В этом случае только некоторые изменения, внесенные в file1.cc, были проиндексированы / проиндексированы для следующей фиксации.

Я запускаю сценарий предварительной фиксации, чтобы запустить проверку стиля:

#!/bin/bash                                                                                                                                                                     

git stash -q --keep-index

# Do the checks                                                                                                                                                                 
RESULT=0
while read status file
do
    if python ~/python/cpplint.py "$file"; then
        let RESULT=1
    fi
done < <(git diff --cached --name-status --diff-filter=ACM | grep -P  '\.((cc)|(h)|(cpp)|(c))$' )

git stash pop -q

[ $RESULT -ne 0 ] && exit 1
exit 0

Как было предложено здесь, я прячу неустановленные файлы, прежде чем я провожу проверки стиля, а потом вставляю их. Однако в случае, когда только некоторые изменения в файле были поставлены, это вызывает конфликт слияния, когда я вставляю тайник в конец ловушки предварительной фиксации.

Как лучше это сделать? Я хочу выполнить проверку стиля для поэтапной версии файлов, которые собираются зафиксировать.


person Community    schedule 08.12.2012    source источник
comment
возможный дубликат Показать полные файлы в том виде, в каком они существуют в индексе git   -  person William Pursell    schedule 08.12.2012
comment
Я думаю, что принятый ответ лучше для моих целей, чем любой здесь (я пытаюсь передать файлы в несколько разных проверок стиля).   -  person Dogmatixed    schedule 07.02.2014


Ответы (3)


Я бы не стал использовать git stash автоматически в хуках. Я обнаружил, что можно использовать git show ':filename' для получения содержимого сохраненного файла.
Вместо этого я использовал следующий подход:

git diff --cached --name-only --diff-filter=ACMR | while read filename; do
    git show ":$filename" | GIT_VERIFY_FILENAME="$filename" verify_copyright \
        || exit $?
done \
    || exit $?
person ony    schedule 04.07.2013

Замените git stash -q --keep-index на:

git diff --full-index --binary > /tmp/stash.$$
git stash -q --keep-index

... и git stash pop -q с:

git apply --whitespace=nowarn < /tmp/stash.$$` && git stash drop -q
rm /tmp/stash.$$

Это сохранит разницу во временный файл и повторно применит его, используя git apply в конце. Изменения по-прежнему избыточно сохраняются в тайнике (который позже удаляется), поэтому, если что-то пойдет не так с повторным применением, вы можете проверить их, используя git stash show -p, без необходимости искать временный файл.

person user4815162342    schedule 09.12.2012

Как гейт-коммиты без сохранения

Мы используем этот .git/hooks/pre-commit для проверки пакета синтаксиса атома

Ключевые биты

  1. git checkout-index -a --prefix={{temp_dir}}

Это может / не может быть намного медленнее / занимать больше места, чем хранение, но автоматизация, которая портит индекс, кажется по своей сути хрупкой. Возможно, нужен сценарий git contrib, который создает дерево программных / жестких ссылок, минимальное пространство только для чтения, временную проверку индекса, облегчая выполнение более / более быстрых .git/hooks/pre-commit (или, скажем, .git/hooks/pre-commit-index) сценариев, чтобы создать полную вторую копию рабочий каталог не нужен, изменяется только рабочий каталог-> index.

#!/usr/bin/env ruby
require 'tmpdir'
autoload :FileUtils,  'fileutils'
autoload :Open3,      'open3'
autoload :Shellwords, 'shellwords'

# ---- setup

INTERACTIVE         = $stdout.tty? || $stderr.tty?
DOT                 = -'.'
BLOCK_SIZE          = 4096
TEMP_INDEX_DIR      = Dir.mktmpdir
TEMP_INDEX_DIR_REAL = File.realpath(TEMP_INDEX_DIR)

def cleanup
  FileUtils.remove_entry(TEMP_INDEX_DIR) if File.exist? TEMP_INDEX_DIR
end

at_exit { cleanup }

%w[INT TERM PIPE HUP QUIT].each do |sig|
  Signal.trap(sig) { cleanup }
end

# ---- functions

def fix_up_dir_output(data)
  data.gsub! TEMP_INDEX_DIR_REAL, DOT
  data.gsub! TEMP_INDEX_DIR, DOT
  data
end

def sh(*args)
  Open3.popen3(*args) do |_, stdout, stderr, w_thr|
    files = [stdout, stderr]
    until files.empty? do
      if ready = IO.select(files)
        ready[0].each do |f|
          begin
            data = f.read_nonblock BLOCK_SIZE
            data = fix_up_dir_output data
            if f.fileno == stderr.fileno
              $stderr.write data
            else
              $stdout.write data
            end
          rescue EOFError
            files.delete f
          end
        end
      end
    end
    if !(done = w_thr.value).success?
      exit(done.exitstatus)
    end
  end
end

def flags(args)
  skip = false
  r = []
  args.each do |a|
    if a[0] == '-' && !skip
      a.slice! 0
      if a[0] == '-'
        skip ||= a[1].nil?
        a.slice! 0
        r << a unless a.empty?
      else # -[^-]+
        r += a.split ''
      end
    end
  end
  r
end

def less_lint
  args = %w[lessc --lint]
  args << '--no-color' unless INTERACTIVE
  args << 'index.less'
  sh(*args)
end

def ensure_git_commit_signed
  pcmd = `ps -wwp#{Process.ppid} -ocommand=`.chop
  args = flags(Shellwords.split(pcmd)[1..-1])
  return unless (args & %w[gpg-sign S]).empty?
  $stderr.puts 'All git commits must be GPG-signed'
  $stderr.puts "    command: #{pcmd}"
  exit 1
end

# ---- main

# 1. make sure all commits are signed
ensure_git_commit_signed

# 2. check files that are in the index
sh 'git', 'checkout-index', '-a', "--prefix=#{TEMP_INDEX_DIR}/"
Dir.chdir TEMP_INDEX_DIR do
  # 3. make sure all commits contain only legal .less files
  less_lint
end
person Community    schedule 21.10.2016